From edee078f0af993021c4f0b4346e523204299224e Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 22 Apr 2022 20:57:45 -0400 Subject: [PATCH 01/19] Eliminate last set of failures. --- InstructionSets/68k/Decoder.cpp | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index d5717fedf..3bb266b88 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -225,8 +225,6 @@ template Preinstruction Predecoder::validated } } - case ANDtoRb: case ANDtoRw: case ANDtoRl: - case ORtoRb: case ORtoRw: case ORtoRl: case SUBtoRb: case SUBtoRw: case SUBtoRl: case ADDtoRb: case ADDtoRw: case ADDtoRl: { constexpr bool is_byte = op == ADDtoRb || op == SUBtoRb || op == SUBtoRb || op == ADDtoRb; @@ -243,12 +241,32 @@ template Preinstruction Predecoder::validated } } - case ADDtoMb: case ADDtoMw: case ADDtoMl: - case SUBtoMb: case SUBtoMw: case SUBtoMl: case ANDtoMb: case ANDtoMw: case ANDtoMl: - case ORtoMb: case ORtoMw: case ORtoMl: { + case ORtoMb: case ORtoMw: case ORtoMl: + switch(original.mode<1>()) { + default: return original; + case AddressingMode::DataRegisterDirect: + case AddressingMode::AddressRegisterDirect: + case AddressingMode::ImmediateData: + case AddressingMode::ProgramCounterIndirectWithDisplacement: + case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: + case AddressingMode::None: + return Preinstruction(); + } + + case ANDtoRb: case ANDtoRw: case ANDtoRl: + case ORtoRb: case ORtoRw: case ORtoRl: + switch(original.mode<0>()) { + default: return original; + case AddressingMode::AddressRegisterDirect: + case AddressingMode::None: + return Preinstruction(); + } + + case ADDtoMb: case ADDtoMw: case ADDtoMl: + case SUBtoMb: case SUBtoMw: case SUBtoMl: { // TODO: I'm going to need get-size-by-operation elsewhere; use that here when implemented. - constexpr bool is_byte = op == ADDtoMb || op == SUBtoMb || op == ANDtoMb || op == ORtoMb; + constexpr bool is_byte = op == ADDtoMb || op == SUBtoMb; switch(original.mode<0>()) { default: break; From 959db77b882d7bfbf98b0fff54d6bc7216afe3ac Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 22 Apr 2022 20:59:25 -0400 Subject: [PATCH 02/19] Eliminate concept of skips. --- OSBindings/Mac/Clock SignalTests/m68kDecoderTests.mm | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/m68kDecoderTests.mm b/OSBindings/Mac/Clock SignalTests/m68kDecoderTests.mm index 180bec077..25fe27552 100644 --- a/OSBindings/Mac/Clock SignalTests/m68kDecoderTests.mm +++ b/OSBindings/Mac/Clock SignalTests/m68kDecoderTests.mm @@ -74,7 +74,6 @@ template NSString *operand(Preinstruction instruction, uint16_t opco XCTAssertNotNil(decodings); Predecoder decoder; - int skipped = 0; for(int instr = 0; instr < 65536; instr++) { NSString *const instrName = [NSString stringWithFormat:@"%04x", instr]; NSString *const expected = decodings[instrName]; @@ -269,7 +268,7 @@ template NSString *operand(Preinstruction instruction, uint16_t opco // For now, skip any unmapped operations. default: - ++skipped; + XCTAssert(false, @"Operation %d unhandled by test case", int(found.operation)); continue; } @@ -282,8 +281,6 @@ template NSString *operand(Preinstruction instruction, uint16_t opco 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); } - - NSLog(@"Skipped %d opcodes", skipped); } @end From b965f2053ac465e9f09b155f162a2c474f74628d Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 24 Apr 2022 10:43:06 -0400 Subject: [PATCH 03/19] Start experimenting with a simple AND for operand validation. --- InstructionSets/68k/Decoder.cpp | 188 +++++++++++++++++++++++++++- InstructionSets/68k/Decoder.hpp | 1 + InstructionSets/68k/Instruction.hpp | 4 +- 3 files changed, 185 insertions(+), 8 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index 3bb266b88..377e6a799 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -37,6 +37,32 @@ constexpr AddressingMode combined_mode(int mode, int reg) { return modes[use_reg]; } +template struct Mask { + static constexpr uint32_t value = 0; +}; + +template struct Mask { + static constexpr uint32_t value = uint32_t(1 << int(F)) | Mask::value; +}; + +static constexpr uint32_t NoOperand = Mask::value; + +template struct TwoOperandMask { + static constexpr uint32_t value = ((first << 16) & 0xffff0000) | (second & 0x0000ffff); +}; + +template struct OneOperandMask { + static constexpr uint32_t value = TwoOperandMask::value; +}; + +struct NoOperandMask { + static constexpr uint32_t value = OneOperandMask::value; +}; + +uint32_t operand_mask(Preinstruction instr) { + return uint32_t((0x1'0000 << int(instr.mode<0>())) | (0x0'0001 << int(instr.mode<1>()))); +} + } // MARK: - Instruction decoders. @@ -115,6 +141,145 @@ constexpr Operation Predecoder::operation(OpT op) { return Operation::Undefined; } +template +template uint32_t Predecoder::invalid_operands() { + // A few recurring combinations; terminology is directly from + // the Programmers' Reference Manual. + + // + // All modes: the complete set. + // + // (and the complete set without AddressRegisterDirect, for byte operations). + static constexpr uint32_t AllModes = Mask< + AddressingMode::DataRegisterDirect, + AddressingMode::AddressRegisterDirect, + AddressingMode::AddressRegisterIndirect, + AddressingMode::AddressRegisterIndirectWithPostincrement, + AddressingMode::AddressRegisterIndirectWithPredecrement, + AddressingMode::AddressRegisterIndirectWithDisplacement, + AddressingMode::AddressRegisterIndirectWithIndex8bitDisplacement, + AddressingMode::AbsoluteShort, + AddressingMode::AbsoluteLong, + AddressingMode::ImmediateData, + AddressingMode::ProgramCounterIndirectWithDisplacement, + AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement + >::value; + static constexpr uint32_t AllModes_b = Mask< + AddressingMode::DataRegisterDirect, + AddressingMode::AddressRegisterIndirect, + AddressingMode::AddressRegisterIndirectWithPostincrement, + AddressingMode::AddressRegisterIndirectWithPredecrement, + AddressingMode::AddressRegisterIndirectWithDisplacement, + AddressingMode::AddressRegisterIndirectWithIndex8bitDisplacement, + AddressingMode::AbsoluteShort, + AddressingMode::AbsoluteLong, + AddressingMode::ImmediateData, + AddressingMode::ProgramCounterIndirectWithDisplacement, + AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement + >::value; + + // + // Alterable addressing modes (with and without AddressRegisterDirect). + // + // Dn, An, (An), (An)+, -(An), (d16, An), (d8, An, Xn), (xxx).W, (xxx).L + // (and sans An for _b) + static constexpr uint32_t AlterableAddressingModes = Mask< + AddressingMode::DataRegisterDirect, + AddressingMode::AddressRegisterDirect, + AddressingMode::AddressRegisterIndirect, + AddressingMode::AddressRegisterIndirectWithPostincrement, + AddressingMode::AddressRegisterIndirectWithPredecrement, + AddressingMode::AddressRegisterIndirectWithDisplacement, + AddressingMode::AddressRegisterIndirectWithIndex8bitDisplacement, + AddressingMode::AbsoluteShort, + AddressingMode::AbsoluteLong + >::value; + static constexpr uint32_t AlterableAddressingModes_b = Mask< + AddressingMode::DataRegisterDirect, + AddressingMode::AddressRegisterIndirect, + AddressingMode::AddressRegisterIndirectWithPostincrement, + AddressingMode::AddressRegisterIndirectWithPredecrement, + AddressingMode::AddressRegisterIndirectWithDisplacement, + AddressingMode::AddressRegisterIndirectWithIndex8bitDisplacement, + AddressingMode::AbsoluteShort, + AddressingMode::AbsoluteLong + >::value; + + switch(op) { + default: return NoOperandMask::value; + + case OpT(Operation::ABCD): + case OpT(Operation::ADDXb): case OpT(Operation::ADDXw): case OpT(Operation::ADDXl): + return ~TwoOperandMask::value, Mask< + AddressingMode::DataRegisterDirect, + AddressingMode::AddressRegisterIndirectWithPredecrement + >::value>::value; + + case ADDtoRb: + return ~TwoOperandMask< + AllModes_b + , Mask< + AddressingMode::DataRegisterDirect + >::value>::value; + + case ADDtoRw: case ADDtoRl: + return ~TwoOperandMask< + AllModes + , Mask< + AddressingMode::DataRegisterDirect + >::value>::value; + + case ADDtoMb: case ADDtoMw: case ADDtoMl: + return ~TwoOperandMask::value, Mask< + // TODO: I strongly suspect this should be AlterableAddressingModes regardless + // of the documentation. Verify. + AddressingMode::AddressRegisterIndirect, + AddressingMode::AddressRegisterIndirectWithPostincrement, + AddressingMode::AddressRegisterIndirectWithPredecrement, + AddressingMode::AddressRegisterIndirectWithDisplacement, + AddressingMode::AddressRegisterIndirectWithIndex8bitDisplacement, + AddressingMode::AbsoluteShort, + AddressingMode::AbsoluteLong + >::value>::value; + + case OpT(Operation::ADDAw): case OpT(Operation::ADDAl): + return ~TwoOperandMask< + AllModes + , Mask< + AddressingMode::AddressRegisterDirect + >::value>::value; + + case ADDIb: case ADDIl: case ADDIw: + return ~TwoOperandMask::value, + AlterableAddressingModes_b + >::value; + + case ADDQb: + return ~TwoOperandMask::value, + AlterableAddressingModes_b + >::value; + + case ADDQw: case ADDQl: + return ~TwoOperandMask::value, + AlterableAddressingModes + >::value; + + case OpT(Operation::NBCD): + return ~OneOperandMask::value; + } +} + /// Provides a post-decoding validation step — primarily ensures that the prima facie addressing modes are supported by the operation. // TODO: once complete and working, see how ugly it would be to incorpoate these tests into the main // decoding switches. @@ -128,7 +293,19 @@ template Preinstruction Predecoder::validated default: return original; // NBCD. - case OpT(Operation::NBCD): + case OpT(Operation::ABCD): + case OpT(Operation::ADDXb): case OpT(Operation::ADDXw): case OpT(Operation::ADDXl): + case ADDtoRb: case ADDtoRw: case ADDtoRl: + case ADDIb: case ADDIl: case ADDIw: + case ADDtoMb: case ADDtoMw: case ADDtoMl: + case OpT(Operation::ADDAw): case OpT(Operation::ADDAl): + case ADDQb: case ADDQw: case ADDQl: + case OpT(Operation::NBCD): { + const auto invalid = invalid_operands(); + const auto observed = operand_mask(original); + return (observed & invalid) ? Preinstruction() : original; + } + case OpT(Operation::MOVEfromSR): case OpT(Operation::TAS): switch(original.mode<0>()) { @@ -157,7 +334,6 @@ template Preinstruction Predecoder::validated case ORIb: case ORIl: case ORIw: case ANDIb: case ANDIl: case ANDIw: case SUBIb: case SUBIl: case SUBIw: - case ADDIb: case ADDIl: case ADDIw: switch(original.mode<1>()) { default: return original; @@ -187,7 +363,7 @@ template Preinstruction Predecoder::validated } // ADD, SUB, MOVE, MOVEA - case ADDQb: case ADDQw: case ADDQl: +// case ADDQb: case ADDQw: case ADDQl: 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): @@ -226,7 +402,7 @@ template Preinstruction Predecoder::validated } case SUBtoRb: case SUBtoRw: case SUBtoRl: - case ADDtoRb: case ADDtoRw: case ADDtoRl: { + /*case ADDtoRb: case ADDtoRw: case ADDtoRl: */{ constexpr bool is_byte = op == ADDtoRb || op == SUBtoRb || op == SUBtoRb || op == ADDtoRb; switch(original.mode<0>()) { @@ -263,7 +439,7 @@ template Preinstruction Predecoder::validated return Preinstruction(); } - case ADDtoMb: case ADDtoMw: case ADDtoMl: + /*case ADDtoMb: case ADDtoMw: case ADDtoMl:*/ case SUBtoMb: case SUBtoMw: case SUBtoMl: { // TODO: I'm going to need get-size-by-operation elsewhere; use that here when implemented. constexpr bool is_byte = op == ADDtoMb || op == SUBtoMb; @@ -313,7 +489,7 @@ template Preinstruction Predecoder::validated } // ADDA, SUBA. - case OpT(Operation::ADDAw): case OpT(Operation::ADDAl): +// case OpT(Operation::ADDAw): case OpT(Operation::ADDAl): case OpT(Operation::SUBAw): case OpT(Operation::SUBAl): switch(original.mode<0>()) { default: break; diff --git a/InstructionSets/68k/Decoder.hpp b/InstructionSets/68k/Decoder.hpp index ac997400f..ed86abe7f 100644 --- a/InstructionSets/68k/Decoder.hpp +++ b/InstructionSets/68k/Decoder.hpp @@ -49,6 +49,7 @@ template class Predecoder { // Specific instruction decoders. template Preinstruction decode(uint16_t instruction); template Preinstruction validated(Preinstruction original); + template uint32_t invalid_operands(); // Extended operation list; collapses into a single byte enough information to // know both the type of operation and how to decode the operands. Most of the diff --git a/InstructionSets/68k/Instruction.hpp b/InstructionSets/68k/Instruction.hpp index 77d9dc75c..57a5cff76 100644 --- a/InstructionSets/68k/Instruction.hpp +++ b/InstructionSets/68k/Instruction.hpp @@ -187,7 +187,7 @@ constexpr int8_t quick(Operation op, uint16_t instruction) { /// as ProgramCounterIndirectWithIndex8bitDisplacement. enum class AddressingMode: uint8_t { /// No adddressing mode; this operand doesn't exist. - None = 0b11'111, + None = 0b01'101, /// Dn DataRegisterDirect = 0b00'000, @@ -232,7 +232,7 @@ enum class AddressingMode: uint8_t { ImmediateData = 0b01'100, /// .q; value is embedded in the opcode. - Quick = 0b11'110, + Quick = 0b01'110, }; /*! From 94e5436f6e4835183c5382c4be497407e6292100 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 24 Apr 2022 14:47:14 -0400 Subject: [PATCH 04/19] Attempt a more compact retelling. --- InstructionSets/68k/Decoder.cpp | 163 +++++++++----------------------- 1 file changed, 46 insertions(+), 117 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index 377e6a799..43c491a5e 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -143,140 +143,95 @@ constexpr Operation Predecoder::operation(OpT op) { template template uint32_t Predecoder::invalid_operands() { + constexpr auto Dn = Mask< AddressingMode::DataRegisterDirect >::value; + constexpr auto An = Mask< AddressingMode::AddressRegisterDirect >::value; + constexpr auto Ind = Mask< AddressingMode::AddressRegisterIndirect >::value; + constexpr auto PostInc = Mask< AddressingMode::AddressRegisterIndirectWithPostincrement >::value; + constexpr auto PreDec = Mask< AddressingMode::AddressRegisterIndirectWithPredecrement >::value; + constexpr auto d16An = Mask< AddressingMode::AddressRegisterIndirectWithDisplacement >::value; + constexpr auto d8AnXn = Mask< AddressingMode::AddressRegisterIndirectWithIndex8bitDisplacement >::value; + constexpr auto XXXw = Mask< AddressingMode::AbsoluteShort >::value; + constexpr auto XXXl = Mask< AddressingMode::AbsoluteLong >::value; + constexpr auto d16PC = Mask< AddressingMode::ProgramCounterIndirectWithDisplacement >::value; + constexpr auto d8PCXn = Mask< AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement >::value; + constexpr auto Imm = Mask< AddressingMode::ImmediateData >::value; + constexpr auto Quick = Mask< AddressingMode::Quick >::value; + + // A few recurring combinations; terminology is directly from // the Programmers' Reference Manual. // - // All modes: the complete set. + // All modes: the complete set (other than Quick). // // (and the complete set without AddressRegisterDirect, for byte operations). - static constexpr uint32_t AllModes = Mask< - AddressingMode::DataRegisterDirect, - AddressingMode::AddressRegisterDirect, - AddressingMode::AddressRegisterIndirect, - AddressingMode::AddressRegisterIndirectWithPostincrement, - AddressingMode::AddressRegisterIndirectWithPredecrement, - AddressingMode::AddressRegisterIndirectWithDisplacement, - AddressingMode::AddressRegisterIndirectWithIndex8bitDisplacement, - AddressingMode::AbsoluteShort, - AddressingMode::AbsoluteLong, - AddressingMode::ImmediateData, - AddressingMode::ProgramCounterIndirectWithDisplacement, - AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement - >::value; - static constexpr uint32_t AllModes_b = Mask< - AddressingMode::DataRegisterDirect, - AddressingMode::AddressRegisterIndirect, - AddressingMode::AddressRegisterIndirectWithPostincrement, - AddressingMode::AddressRegisterIndirectWithPredecrement, - AddressingMode::AddressRegisterIndirectWithDisplacement, - AddressingMode::AddressRegisterIndirectWithIndex8bitDisplacement, - AddressingMode::AbsoluteShort, - AddressingMode::AbsoluteLong, - AddressingMode::ImmediateData, - AddressingMode::ProgramCounterIndirectWithDisplacement, - AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement - >::value; + static constexpr auto AllModes = Dn | An | Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn | Imm; + static constexpr auto AllModes_b = AllModes & ~An; // // Alterable addressing modes (with and without AddressRegisterDirect). // // Dn, An, (An), (An)+, -(An), (d16, An), (d8, An, Xn), (xxx).W, (xxx).L // (and sans An for _b) - static constexpr uint32_t AlterableAddressingModes = Mask< - AddressingMode::DataRegisterDirect, - AddressingMode::AddressRegisterDirect, - AddressingMode::AddressRegisterIndirect, - AddressingMode::AddressRegisterIndirectWithPostincrement, - AddressingMode::AddressRegisterIndirectWithPredecrement, - AddressingMode::AddressRegisterIndirectWithDisplacement, - AddressingMode::AddressRegisterIndirectWithIndex8bitDisplacement, - AddressingMode::AbsoluteShort, - AddressingMode::AbsoluteLong - >::value; - static constexpr uint32_t AlterableAddressingModes_b = Mask< - AddressingMode::DataRegisterDirect, - AddressingMode::AddressRegisterIndirect, - AddressingMode::AddressRegisterIndirectWithPostincrement, - AddressingMode::AddressRegisterIndirectWithPredecrement, - AddressingMode::AddressRegisterIndirectWithDisplacement, - AddressingMode::AddressRegisterIndirectWithIndex8bitDisplacement, - AddressingMode::AbsoluteShort, - AddressingMode::AbsoluteLong - >::value; + static constexpr auto AlterableAddressingModes = Dn | An | Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl; + static constexpr auto AlterableAddressingModes_b = AlterableAddressingModes & ~An; switch(op) { default: return NoOperandMask::value; case OpT(Operation::ABCD): case OpT(Operation::ADDXb): case OpT(Operation::ADDXw): case OpT(Operation::ADDXl): - return ~TwoOperandMask::value, Mask< - AddressingMode::DataRegisterDirect, - AddressingMode::AddressRegisterIndirectWithPredecrement - >::value>::value; + return ~TwoOperandMask< + Dn | PreDec, + Dn | PreDec + >::value; case ADDtoRb: return ~TwoOperandMask< - AllModes_b - , Mask< - AddressingMode::DataRegisterDirect - >::value>::value; + AllModes_b, + Dn + >::value; case ADDtoRw: case ADDtoRl: return ~TwoOperandMask< - AllModes - , Mask< - AddressingMode::DataRegisterDirect - >::value>::value; + AllModes, + Dn + >::value; case ADDtoMb: case ADDtoMw: case ADDtoMl: - return ~TwoOperandMask::value, Mask< - // TODO: I strongly suspect this should be AlterableAddressingModes regardless - // of the documentation. Verify. - AddressingMode::AddressRegisterIndirect, - AddressingMode::AddressRegisterIndirectWithPostincrement, - AddressingMode::AddressRegisterIndirectWithPredecrement, - AddressingMode::AddressRegisterIndirectWithDisplacement, - AddressingMode::AddressRegisterIndirectWithIndex8bitDisplacement, - AddressingMode::AbsoluteShort, - AddressingMode::AbsoluteLong - >::value>::value; + return ~TwoOperandMask< + Dn, + Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl + >::value; case OpT(Operation::ADDAw): case OpT(Operation::ADDAl): return ~TwoOperandMask< - AllModes - , Mask< - AddressingMode::AddressRegisterDirect - >::value>::value; + AllModes, + An + >::value; case ADDIb: case ADDIl: case ADDIw: - return ~TwoOperandMask::value, + return ~TwoOperandMask< + Imm, AlterableAddressingModes_b >::value; case ADDQb: - return ~TwoOperandMask::value, + return ~TwoOperandMask< + Quick, AlterableAddressingModes_b >::value; case ADDQw: case ADDQl: - return ~TwoOperandMask::value, + return ~TwoOperandMask< + Quick, AlterableAddressingModes >::value; case OpT(Operation::NBCD): - return ~OneOperandMask::value; + return ~OneOperandMask< + AlterableAddressingModes_b + >::value; } } @@ -363,11 +318,9 @@ template Preinstruction Predecoder::validated } // ADD, SUB, MOVE, MOVEA -// case ADDQb: case ADDQw: case ADDQl: 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::ANDb): case OpT(Operation::ANDw): case OpT(Operation::ANDl): case OpT(Operation::EORb): case OpT(Operation::EORw): case OpT(Operation::EORl): case OpT(Operation::ORb): case OpT(Operation::ORw): case OpT(Operation::ORl): { // TODO: I'm going to need get-size-by-operation elsewhere; use that here when implemented. @@ -724,31 +677,7 @@ template Preinstruction Predecoder::decode(ui // b0–b2 and b3–b5: an effective address; // b6–b8: an opmode, i.e. source + direction. // - case OpT(Operation::SUBb): case OpT(Operation::SUBw): case OpT(Operation::SUBl): - case OpT(Operation::ANDb): case OpT(Operation::ANDw): case OpT(Operation::ANDl): - case OpT(Operation::ORb): case OpT(Operation::ORw): case OpT(Operation::ORl): { - const auto ea_combined_mode = combined_mode(ea_mode, ea_register); - - // TODO: make this decision outside of this function. - if(opmode & 4) { - // Dn, - - return validated( - Preinstruction(operation, - AddressingMode::DataRegisterDirect, data_register, - ea_combined_mode, ea_register)); - } else { - // , Dn - - return validated( - Preinstruction(operation, - ea_combined_mode, ea_register, - AddressingMode::DataRegisterDirect, data_register)); - } - - return Preinstruction(); - } case ADDtoRb: case ADDtoRw: case ADDtoRl: From 87178ed72536eed6a95cfcb5ae8a06de0b5ff9e3 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 24 Apr 2022 15:12:18 -0400 Subject: [PATCH 05/19] Port AND. --- InstructionSets/68k/Decoder.cpp | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index 43c491a5e..e3eceeab5 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -164,17 +164,14 @@ template uint32_t Predecoder::invalid_operands() { // // All modes: the complete set (other than Quick). // - // (and the complete set without AddressRegisterDirect, for byte operations). static constexpr auto AllModes = Dn | An | Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn | Imm; - static constexpr auto AllModes_b = AllModes & ~An; + static constexpr auto AllModesNoAn = AllModes & ~An; // // Alterable addressing modes (with and without AddressRegisterDirect). // - // Dn, An, (An), (An)+, -(An), (d16, An), (d8, An, Xn), (xxx).W, (xxx).L - // (and sans An for _b) static constexpr auto AlterableAddressingModes = Dn | An | Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl; - static constexpr auto AlterableAddressingModes_b = AlterableAddressingModes & ~An; + static constexpr auto AlterableAddressingModesNoAn = AlterableAddressingModes & ~An; switch(op) { default: return NoOperandMask::value; @@ -187,8 +184,9 @@ template uint32_t Predecoder::invalid_operands() { >::value; case ADDtoRb: + case ANDtoRb: case ANDtoRw: case ANDtoRl: return ~TwoOperandMask< - AllModes_b, + AllModesNoAn, Dn >::value; @@ -199,6 +197,7 @@ template uint32_t Predecoder::invalid_operands() { >::value; case ADDtoMb: case ADDtoMw: case ADDtoMl: + case ANDtoMb: case ANDtoMw: case ANDtoMl: return ~TwoOperandMask< Dn, Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl @@ -211,15 +210,16 @@ template uint32_t Predecoder::invalid_operands() { >::value; case ADDIb: case ADDIl: case ADDIw: + case ANDIb: case ANDIl: case ANDIw: return ~TwoOperandMask< Imm, - AlterableAddressingModes_b + AlterableAddressingModesNoAn >::value; case ADDQb: return ~TwoOperandMask< Quick, - AlterableAddressingModes_b + AlterableAddressingModesNoAn >::value; case ADDQw: case ADDQl: @@ -228,9 +228,14 @@ template uint32_t Predecoder::invalid_operands() { AlterableAddressingModes >::value; + case OpT(Operation::ANDItoCCR): + return ~OneOperandMask< + Imm + >::value; + case OpT(Operation::NBCD): return ~OneOperandMask< - AlterableAddressingModes_b + AlterableAddressingModesNoAn >::value; } } @@ -247,7 +252,7 @@ template Preinstruction Predecoder::validated switch(op) { default: return original; - // NBCD. + // All operations converted to the AND test. case OpT(Operation::ABCD): case OpT(Operation::ADDXb): case OpT(Operation::ADDXw): case OpT(Operation::ADDXl): case ADDtoRb: case ADDtoRw: case ADDtoRl: @@ -255,6 +260,10 @@ template Preinstruction Predecoder::validated case ADDtoMb: case ADDtoMw: case ADDtoMl: case OpT(Operation::ADDAw): case OpT(Operation::ADDAl): case ADDQb: case ADDQw: case ADDQl: + case ANDtoRb: case ANDtoRw: case ANDtoRl: + case ANDtoMb: case ANDtoMw: case ANDtoMl: + case ANDIb: case ANDIl: case ANDIw: + case OpT(Operation::ANDItoCCR): case OpT(Operation::NBCD): { const auto invalid = invalid_operands(); const auto observed = operand_mask(original); @@ -287,7 +296,6 @@ template Preinstruction Predecoder::validated // The various immediates. case EORIb: case EORIl: case EORIw: case ORIb: case ORIl: case ORIw: - case ANDIb: case ANDIl: case ANDIw: case SUBIb: case SUBIl: case SUBIw: switch(original.mode<1>()) { default: return original; @@ -370,7 +378,6 @@ template Preinstruction Predecoder::validated } } - case ANDtoMb: case ANDtoMw: case ANDtoMl: case ORtoMb: case ORtoMw: case ORtoMl: switch(original.mode<1>()) { default: return original; @@ -383,7 +390,6 @@ template Preinstruction Predecoder::validated return Preinstruction(); } - case ANDtoRb: case ANDtoRw: case ANDtoRl: case ORtoRb: case ORtoRw: case ORtoRl: switch(original.mode<0>()) { default: return original; From 4f4a2e6d921ca59723f4dfb16348e9f122487d44 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 24 Apr 2022 19:53:54 -0400 Subject: [PATCH 06/19] Translate ASL, ASR, Bcc, BCHG, BCLR. --- InstructionSets/68k/Decoder.cpp | 34 ++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index e3eceeab5..040a32730 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -228,11 +228,36 @@ template uint32_t Predecoder::invalid_operands() { AlterableAddressingModes >::value; + case OpT(Operation::Bccw): case OpT(Operation::Bccl): case OpT(Operation::ANDItoCCR): return ~OneOperandMask< Imm >::value; + case OpT(Operation::ASLb): case OpT(Operation::ASLw): case OpT(Operation::ASLl): + case OpT(Operation::ASRb): case OpT(Operation::ASRw): case OpT(Operation::ASRl): + return ~TwoOperandMask< + Quick | Dn, + Dn + >::value; + + case OpT(Operation::Bccb): + return ~OneOperandMask< + Quick + >::value; + + case OpT(Operation::BCHG): case OpT(Operation::BCLR): + return ~TwoOperandMask< + Dn, + AlterableAddressingModesNoAn + >::value; + + case BCHGI: case BCLRI: + return ~TwoOperandMask< + Imm, + AlterableAddressingModesNoAn + >::value; + case OpT(Operation::NBCD): return ~OneOperandMask< AlterableAddressingModesNoAn @@ -264,6 +289,11 @@ template Preinstruction Predecoder::validated case ANDtoMb: case ANDtoMw: case ANDtoMl: case ANDIb: case ANDIl: case ANDIw: case OpT(Operation::ANDItoCCR): + case OpT(Operation::ASLb): case OpT(Operation::ASLw): case OpT(Operation::ASLl): + case OpT(Operation::ASRb): case OpT(Operation::ASRw): case OpT(Operation::ASRl): + case OpT(Operation::Bccb): case OpT(Operation::Bccw): case OpT(Operation::Bccl): + case OpT(Operation::BCHG): case BCHGI: + case OpT(Operation::BCLR): case BCLRI: case OpT(Operation::NBCD): { const auto invalid = invalid_operands(); const auto observed = operand_mask(original); @@ -489,9 +519,7 @@ template Preinstruction Predecoder::validated return Preinstruction(); } - case OpT(Operation::BCHG): - case OpT(Operation::BSET): case OpT(Operation::BCLR): - case BCHGI: case BSETI: case BCLRI: + case OpT(Operation::BSET): case BSETI: switch(original.mode<1>()) { default: return original; From 03caa5386326b83313941e6507ed2eff1a22f89d Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 24 Apr 2022 19:58:10 -0400 Subject: [PATCH 07/19] Translate BSET. --- InstructionSets/68k/Decoder.cpp | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index 040a32730..c539b275d 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -246,13 +246,15 @@ template uint32_t Predecoder::invalid_operands() { Quick >::value; - case OpT(Operation::BCHG): case OpT(Operation::BCLR): + case OpT(Operation::BCHG): + case OpT(Operation::BCLR): + case OpT(Operation::BSET): return ~TwoOperandMask< Dn, AlterableAddressingModesNoAn >::value; - case BCHGI: case BCLRI: + case BCHGI: case BCLRI: case BSETI: return ~TwoOperandMask< Imm, AlterableAddressingModesNoAn @@ -294,6 +296,7 @@ template Preinstruction Predecoder::validated case OpT(Operation::Bccb): case OpT(Operation::Bccw): case OpT(Operation::Bccl): case OpT(Operation::BCHG): case BCHGI: case OpT(Operation::BCLR): case BCLRI: + case OpT(Operation::BSET): case BSETI: case OpT(Operation::NBCD): { const auto invalid = invalid_operands(); const auto observed = operand_mask(original); @@ -477,8 +480,6 @@ template Preinstruction Predecoder::validated return Preinstruction(); } - // ADDA, SUBA. -// case OpT(Operation::ADDAw): case OpT(Operation::ADDAl): case OpT(Operation::SUBAw): case OpT(Operation::SUBAl): switch(original.mode<0>()) { default: break; @@ -519,18 +520,6 @@ template Preinstruction Predecoder::validated return Preinstruction(); } - case OpT(Operation::BSET): case BSETI: - switch(original.mode<1>()) { - default: return original; - - case AddressingMode::None: - case AddressingMode::AddressRegisterDirect: - case AddressingMode::ProgramCounterIndirectWithDisplacement: - case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: - case AddressingMode::ImmediateData: - return Preinstruction(); - } - case BTSTI: switch(original.mode<1>()) { default: return original; From d01fa96177fcd73f6b5be0168b3ee43e9f1617d5 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 24 Apr 2022 20:49:41 -0400 Subject: [PATCH 08/19] Port BSR, BTST. --- InstructionSets/68k/Decoder.cpp | 40 +++++++++++++++------------------ 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index c539b275d..14b6859b7 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -228,8 +228,9 @@ template uint32_t Predecoder::invalid_operands() { AlterableAddressingModes >::value; - case OpT(Operation::Bccw): case OpT(Operation::Bccl): case OpT(Operation::ANDItoCCR): + case OpT(Operation::Bccw): case OpT(Operation::Bccl): + case OpT(Operation::BSRl): case OpT(Operation::BSRw): return ~OneOperandMask< Imm >::value; @@ -242,6 +243,7 @@ template uint32_t Predecoder::invalid_operands() { >::value; case OpT(Operation::Bccb): + case OpT(Operation::BSRb): return ~OneOperandMask< Quick >::value; @@ -260,6 +262,18 @@ template uint32_t Predecoder::invalid_operands() { AlterableAddressingModesNoAn >::value; + case OpT(Operation::BTST): + return ~TwoOperandMask< + Dn, + AllModesNoAn + >::value; + + case BTSTI: + return ~TwoOperandMask< + Imm, + Dn | Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn + >::value; + case OpT(Operation::NBCD): return ~OneOperandMask< AlterableAddressingModesNoAn @@ -297,6 +311,8 @@ template Preinstruction Predecoder::validated case OpT(Operation::BCHG): case BCHGI: case OpT(Operation::BCLR): case BCLRI: case OpT(Operation::BSET): case BSETI: + case OpT(Operation::BSRb): case OpT(Operation::BSRw): case OpT(Operation::BSRl): + case OpT(Operation::BTST): case BTSTI: case OpT(Operation::NBCD): { const auto invalid = invalid_operands(); const auto observed = operand_mask(original); @@ -395,8 +411,7 @@ template Preinstruction Predecoder::validated } } - case SUBtoRb: case SUBtoRw: case SUBtoRl: - /*case ADDtoRb: case ADDtoRw: case ADDtoRl: */{ + case SUBtoRb: case SUBtoRw: case SUBtoRl: { constexpr bool is_byte = op == ADDtoRb || op == SUBtoRb || op == SUBtoRb || op == ADDtoRb; switch(original.mode<0>()) { @@ -511,25 +526,6 @@ template Preinstruction Predecoder::validated return Preinstruction(); } - case OpT(Operation::BTST): - switch(original.mode<1>()) { - default: return original; - - case AddressingMode::None: - case AddressingMode::AddressRegisterDirect: - return Preinstruction(); - } - - case BTSTI: - switch(original.mode<1>()) { - default: return original; - - case AddressingMode::None: - case AddressingMode::AddressRegisterDirect: - case AddressingMode::ImmediateData: - return Preinstruction(); - } - case OpT(Operation::TSTb): case OpT(Operation::TSTw): case OpT(Operation::TSTl): switch(original.mode<0>()) { default: return original; From f5ea5c26a3252c5f437c6949e5e664a7232ebc48 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 24 Apr 2022 21:05:00 -0400 Subject: [PATCH 09/19] Translate CHK, CLR, CMP, CMPA. --- InstructionSets/68k/Decoder.cpp | 34 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index 14b6859b7..dc17a2ceb 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -185,12 +185,15 @@ template uint32_t Predecoder::invalid_operands() { case ADDtoRb: case ANDtoRb: case ANDtoRw: case ANDtoRl: + case OpT(Operation::CHK): + case OpT(Operation::CMPb): return ~TwoOperandMask< AllModesNoAn, Dn >::value; case ADDtoRw: case ADDtoRl: + case OpT(Operation::CMPw): case OpT(Operation::CMPl): return ~TwoOperandMask< AllModes, Dn @@ -274,10 +277,17 @@ template uint32_t Predecoder::invalid_operands() { Dn | Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn >::value; + case OpT(Operation::CLRb): case OpT(Operation::CLRw): case OpT(Operation::CLRl): case OpT(Operation::NBCD): return ~OneOperandMask< AlterableAddressingModesNoAn >::value; + + case OpT(Operation::CMPAw): case OpT(Operation::CMPAl): + return ~TwoOperandMask< + AllModes, + An + >::value; } } @@ -313,6 +323,10 @@ template Preinstruction Predecoder::validated case OpT(Operation::BSET): case BSETI: case OpT(Operation::BSRb): case OpT(Operation::BSRw): case OpT(Operation::BSRl): case OpT(Operation::BTST): case BTSTI: + case OpT(Operation::CHK): + case OpT(Operation::CLRb): case OpT(Operation::CLRw): case OpT(Operation::CLRl): + case OpT(Operation::CMPb): case OpT(Operation::CMPw): case OpT(Operation::CMPl): + case OpT(Operation::CMPAw): case OpT(Operation::CMPAl): case OpT(Operation::NBCD): { const auto invalid = invalid_operands(); const auto observed = operand_mask(original); @@ -552,24 +566,6 @@ template Preinstruction Predecoder::validated return Preinstruction(); } - case OpT(Operation::CMPAw): case OpT(Operation::CMPAl): - case OpT(Operation::CMPw): case OpT(Operation::CMPl): - switch(original.mode<0>()) { - default: return original; - - case AddressingMode::None: - return Preinstruction(); - } - - case OpT(Operation::CMPb): - switch(original.mode<0>()) { - default: return original; - - case AddressingMode::None: - case AddressingMode::AddressRegisterDirect: - return Preinstruction(); - } - case OpT(Operation::JSR): case OpT(Operation::JMP): switch(original.mode<0>()) { default: return original; @@ -585,7 +581,6 @@ template Preinstruction Predecoder::validated case OpT(Operation::Scc): case OpT(Operation::NEGXb): case OpT(Operation::NEGXw): case OpT(Operation::NEGXl): - case OpT(Operation::CLRb): case OpT(Operation::CLRw): case OpT(Operation::CLRl): case OpT(Operation::NEGb): case OpT(Operation::NEGw): case OpT(Operation::NEGl): switch(original.mode<0>()) { default: return original; @@ -642,7 +637,6 @@ template Preinstruction Predecoder::validated case OpT(Operation::DIVU): case OpT(Operation::DIVS): case OpT(Operation::MULU): case OpT(Operation::MULS): - case OpT(Operation::CHK): switch(original.mode<0>()) { default: return original; From dda0c0e097d876c29d77236287d054cad43aa31d Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 25 Apr 2022 09:39:22 -0400 Subject: [PATCH 10/19] Update CMPM, CMPI. --- InstructionSets/68k/Decoder.cpp | 34 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index dc17a2ceb..cf34409c6 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -271,6 +271,14 @@ template uint32_t Predecoder::invalid_operands() { AllModesNoAn >::value; + case CMPIb: case CMPIl: case CMPIw: + if constexpr (model == Model::M68000) { + return ~TwoOperandMask< + Imm, + Dn | Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl + >::value; + } + [[fallthrough]]; case BTSTI: return ~TwoOperandMask< Imm, @@ -288,6 +296,13 @@ template uint32_t Predecoder::invalid_operands() { AllModes, An >::value; + + case CMPMb: case CMPMw: case CMPMl: + return ~TwoOperandMask< + PostInc, + PostInc + >::value; + } } @@ -327,6 +342,8 @@ template Preinstruction Predecoder::validated case OpT(Operation::CLRb): case OpT(Operation::CLRw): case OpT(Operation::CLRl): case OpT(Operation::CMPb): case OpT(Operation::CMPw): case OpT(Operation::CMPl): case OpT(Operation::CMPAw): case OpT(Operation::CMPAl): + case CMPIb: case CMPIl: case CMPIw: + case CMPMb: case CMPMw: case CMPMl: case OpT(Operation::NBCD): { const auto invalid = invalid_operands(); const auto observed = operand_mask(original); @@ -371,23 +388,6 @@ template Preinstruction Predecoder::validated return Preinstruction(); } - case CMPIb: case CMPIl: case CMPIw: - switch(original.mode<1>()) { - default: return original; - - case AddressingMode::ProgramCounterIndirectWithDisplacement: - case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: - if constexpr (model >= Model::M68010) { - return original; - } - [[fallthrough]]; - - case AddressingMode::AddressRegisterDirect: - case AddressingMode::ImmediateData: - case AddressingMode::None: - return Preinstruction(); - } - // ADD, SUB, MOVE, MOVEA case SUBQb: case SUBQw: case SUBQl: case OpT(Operation::MOVEb): case OpT(Operation::MOVEw): case OpT(Operation::MOVEl): From 27f8db6e8bc07697ff538ec0de6662a9df7a01fb Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 25 Apr 2022 09:49:18 -0400 Subject: [PATCH 11/19] Update DBcc, DIVU/DIVS, EOR. --- InstructionSets/68k/Decoder.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index cf34409c6..e1893f625 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -254,12 +254,14 @@ template uint32_t Predecoder::invalid_operands() { case OpT(Operation::BCHG): case OpT(Operation::BCLR): case OpT(Operation::BSET): + case OpT(Operation::EORb): case OpT(Operation::EORw): case OpT(Operation::EORl): return ~TwoOperandMask< Dn, AlterableAddressingModesNoAn >::value; case BCHGI: case BCLRI: case BSETI: + case EORIb: case EORIw: case EORIl: return ~TwoOperandMask< Imm, AlterableAddressingModesNoAn @@ -291,7 +293,7 @@ template uint32_t Predecoder::invalid_operands() { AlterableAddressingModesNoAn >::value; - case OpT(Operation::CMPAw): case OpT(Operation::CMPAl): + case OpT(Operation::CMPAw): case OpT(Operation::CMPAl): return ~TwoOperandMask< AllModes, An @@ -303,6 +305,17 @@ template uint32_t Predecoder::invalid_operands() { PostInc >::value; + case OpT(Operation::DBcc): + return ~TwoOperandMask< + Dn, + Imm + >::value; + + case OpT(Operation::DIVU): case OpT(Operation::DIVS): + return ~TwoOperandMask< + AllModesNoAn, + Dn + >::value; } } @@ -344,6 +357,10 @@ template Preinstruction Predecoder::validated case OpT(Operation::CMPAw): case OpT(Operation::CMPAl): case CMPIb: case CMPIl: case CMPIw: case CMPMb: case CMPMw: case CMPMl: + case OpT(Operation::DBcc): + case OpT(Operation::DIVS): case OpT(Operation::DIVU): + case OpT(Operation::EORb): case OpT(Operation::EORw): case OpT(Operation::EORl): + case EORIb: case EORIw: case EORIl: case OpT(Operation::NBCD): { const auto invalid = invalid_operands(); const auto observed = operand_mask(original); @@ -374,7 +391,6 @@ template Preinstruction Predecoder::validated } // The various immediates. - case EORIb: case EORIl: case EORIw: case ORIb: case ORIl: case ORIw: case SUBIb: case SUBIl: case SUBIw: switch(original.mode<1>()) { @@ -392,7 +408,6 @@ template Preinstruction Predecoder::validated 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::EORb): case OpT(Operation::EORw): case OpT(Operation::EORl): case OpT(Operation::ORb): case OpT(Operation::ORw): case OpT(Operation::ORl): { // TODO: I'm going to need get-size-by-operation elsewhere; use that here when implemented. constexpr bool is_byte = @@ -635,7 +650,6 @@ template Preinstruction Predecoder::validated return Preinstruction(); } - case OpT(Operation::DIVU): case OpT(Operation::DIVS): case OpT(Operation::MULU): case OpT(Operation::MULS): switch(original.mode<0>()) { default: return original; From 9bbd1390c1bc326e2e4a63ccb40725ccf3e0a450 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 25 Apr 2022 11:43:30 -0400 Subject: [PATCH 12/19] Add new-style validation of EORI to CCR, move EXG decoding into page navigation. --- InstructionSets/68k/Decoder.cpp | 44 +++++++++++++++++---------------- InstructionSets/68k/Decoder.hpp | 2 ++ 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index e1893f625..e212bbf14 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -135,6 +135,9 @@ constexpr Operation Predecoder::operation(OpT op) { case ORtoRw: case ORtoMw: return Operation::ORw; case ORtoRl: case ORtoMl: return Operation::ORl; + case EXGRtoR: case EXGAtoA: case EXGRtoA: + return Operation::EXG; + default: break; } @@ -234,6 +237,7 @@ template uint32_t Predecoder::invalid_operands() { case OpT(Operation::ANDItoCCR): case OpT(Operation::Bccw): case OpT(Operation::Bccl): case OpT(Operation::BSRl): case OpT(Operation::BSRw): + case OpT(Operation::EORItoCCR): return ~OneOperandMask< Imm >::value; @@ -361,6 +365,7 @@ template Preinstruction Predecoder::validated case OpT(Operation::DIVS): case OpT(Operation::DIVU): case OpT(Operation::EORb): case OpT(Operation::EORw): case OpT(Operation::EORl): case EORIb: case EORIw: case EORIl: + case OpT(Operation::EORItoCCR): case OpT(Operation::NBCD): { const auto invalid = invalid_operands(); const auto observed = operand_mask(original); @@ -803,26 +808,23 @@ template Preinstruction Predecoder::decode(ui // b9–b11: register Rx (data or address, data if exchange is address <-> data); // b3–b7: an opmode, indicating address/data registers. // - case OpT(Operation::EXG): - switch((instruction >> 3)&31) { - default: return Preinstruction(); + case EXGRtoR: + return validated( + Preinstruction(operation, + AddressingMode::DataRegisterDirect, data_register, + AddressingMode::DataRegisterDirect, ea_register)); - case 0x08: return validated( - Preinstruction(operation, - AddressingMode::DataRegisterDirect, data_register, - AddressingMode::DataRegisterDirect, ea_register)); + case EXGAtoA: + return validated( + Preinstruction(operation, + AddressingMode::AddressRegisterDirect, data_register, + AddressingMode::AddressRegisterDirect, ea_register)); - case 0x09: return validated( - Preinstruction(operation, - AddressingMode::AddressRegisterDirect, data_register, - AddressingMode::AddressRegisterDirect, ea_register)); - - case 0x11: return validated( - Preinstruction(operation, - AddressingMode::DataRegisterDirect, data_register, - AddressingMode::AddressRegisterDirect, ea_register)); - } - // TODO: remove conditional from in here. + case EXGRtoA: + return validated( + Preinstruction(operation, + AddressingMode::DataRegisterDirect, data_register, + AddressingMode::AddressRegisterDirect, ea_register)); // // MARK: MULU, MULS, DIVU, DIVS. @@ -1458,9 +1460,9 @@ Preinstruction Predecoder::decodeC(uint16_t instruction) { // 4-105 (p209) switch(instruction & 0x1f8) { - case 0x140: - case 0x148: - case 0x188: Decode(Op::EXG); + case 0x140: Decode(EXGRtoR); + case 0x148: Decode(EXGAtoA); + case 0x188: Decode(EXGRtoA); default: break; } diff --git a/InstructionSets/68k/Decoder.hpp b/InstructionSets/68k/Decoder.hpp index ed86abe7f..3589e711f 100644 --- a/InstructionSets/68k/Decoder.hpp +++ b/InstructionSets/68k/Decoder.hpp @@ -91,6 +91,8 @@ template class Predecoder { ORtoMb, ORtoMw, ORtoMl, ORtoRb, ORtoRw, ORtoRl, + + EXGRtoR, EXGAtoA, EXGRtoA, }; static constexpr Operation operation(OpT op); From e6dc2e0d3111109c71b7e37a0973f518cf3d0095 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 25 Apr 2022 11:49:14 -0400 Subject: [PATCH 13/19] Add EXG, EXT. --- InstructionSets/68k/Decoder.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index e212bbf14..bffdc8e16 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -320,6 +320,29 @@ template uint32_t Predecoder::invalid_operands() { AllModesNoAn, Dn >::value; + + case EXGRtoR: + return ~TwoOperandMask< + Dn, + Dn + >::value; + + case EXGAtoA: + return ~TwoOperandMask< + An, + An + >::value; + + case EXGRtoA: + return ~TwoOperandMask< + Dn, + An + >::value; + + case OpT(Operation::EXTbtow): case OpT(Operation::EXTwtol): + return ~OneOperandMask< + Dn + >::value; } } @@ -366,6 +389,8 @@ template Preinstruction Predecoder::validated case OpT(Operation::EORb): case OpT(Operation::EORw): case OpT(Operation::EORl): case EORIb: case EORIw: case EORIl: case OpT(Operation::EORItoCCR): + case EXGRtoR: case EXGAtoA: case EXGRtoA: + case OpT(Operation::EXTbtow): case OpT(Operation::EXTwtol): case OpT(Operation::NBCD): { const auto invalid = invalid_operands(); const auto observed = operand_mask(original); From 6ca30a16ca69e55af202c5bbe1643e2de9addd2d Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 25 Apr 2022 12:05:07 -0400 Subject: [PATCH 14/19] Update JMP, JSR. --- InstructionSets/68k/Decoder.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index bffdc8e16..241c68e82 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -343,6 +343,12 @@ template uint32_t Predecoder::invalid_operands() { return ~OneOperandMask< Dn >::value; + + case OpT(Operation::JMP): + case OpT(Operation::JSR): + return ~OneOperandMask< + Ind | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn + >::value; } } @@ -391,6 +397,8 @@ template Preinstruction Predecoder::validated case OpT(Operation::EORItoCCR): case EXGRtoR: case EXGAtoA: case EXGRtoA: case OpT(Operation::EXTbtow): case OpT(Operation::EXTwtol): + case OpT(Operation::JMP): + case OpT(Operation::JSR): case OpT(Operation::NBCD): { const auto invalid = invalid_operands(); const auto observed = operand_mask(original); @@ -505,7 +513,6 @@ template Preinstruction Predecoder::validated return Preinstruction(); } - /*case ADDtoMb: case ADDtoMw: case ADDtoMl:*/ case SUBtoMb: case SUBtoMw: case SUBtoMl: { // TODO: I'm going to need get-size-by-operation elsewhere; use that here when implemented. constexpr bool is_byte = op == ADDtoMb || op == SUBtoMb; @@ -611,19 +618,6 @@ template Preinstruction Predecoder::validated return Preinstruction(); } - case OpT(Operation::JSR): case OpT(Operation::JMP): - switch(original.mode<0>()) { - default: return original; - - case AddressingMode::DataRegisterDirect: - case AddressingMode::AddressRegisterDirect: - case AddressingMode::AddressRegisterIndirectWithPostincrement: - case AddressingMode::AddressRegisterIndirectWithPredecrement: - case AddressingMode::ImmediateData: - case AddressingMode::None: - return Preinstruction(); - } - case OpT(Operation::Scc): case OpT(Operation::NEGXb): case OpT(Operation::NEGXw): case OpT(Operation::NEGXl): case OpT(Operation::NEGb): case OpT(Operation::NEGw): case OpT(Operation::NEGl): From 15385009032404b35ae688c7621451e0535bc430 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 25 Apr 2022 12:30:44 -0400 Subject: [PATCH 15/19] Add enough to make AND masks the default case. --- InstructionSets/68k/Decoder.cpp | 119 ++++++++++++++++---------------- 1 file changed, 59 insertions(+), 60 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index 241c68e82..3f6583a48 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -176,6 +176,11 @@ template uint32_t Predecoder::invalid_operands() { static constexpr auto AlterableAddressingModes = Dn | An | Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl; static constexpr auto AlterableAddressingModesNoAn = AlterableAddressingModes & ~An; + // + // Control [flow] addressing modes. + // + static constexpr auto ControlAddressingModes = Ind | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn; + switch(op) { default: return NoOperandMask::value; @@ -234,23 +239,45 @@ template uint32_t Predecoder::invalid_operands() { AlterableAddressingModes >::value; - case OpT(Operation::ANDItoCCR): + case OpT(Operation::ANDItoCCR): case OpT(Operation::ANDItoSR): case OpT(Operation::Bccw): case OpT(Operation::Bccl): case OpT(Operation::BSRl): case OpT(Operation::BSRw): - case OpT(Operation::EORItoCCR): + case OpT(Operation::EORItoCCR): case OpT(Operation::EORItoSR): + case OpT(Operation::ORItoCCR): case OpT(Operation::ORItoSR): + case OpT(Operation::STOP): return ~OneOperandMask< Imm >::value; case OpT(Operation::ASLb): case OpT(Operation::ASLw): case OpT(Operation::ASLl): case OpT(Operation::ASRb): case OpT(Operation::ASRw): case OpT(Operation::ASRl): + case OpT(Operation::LSLb): case OpT(Operation::LSLw): case OpT(Operation::LSLl): + case OpT(Operation::LSRb): case OpT(Operation::LSRw): case OpT(Operation::LSRl): + case OpT(Operation::ROLb): case OpT(Operation::ROLw): case OpT(Operation::ROLl): + case OpT(Operation::RORb): case OpT(Operation::RORw): case OpT(Operation::RORl): + case OpT(Operation::ROXLb): case OpT(Operation::ROXLw): case OpT(Operation::ROXLl): + case OpT(Operation::ROXRb): case OpT(Operation::ROXRw): case OpT(Operation::ROXRl): return ~TwoOperandMask< Quick | Dn, Dn >::value; + case OpT(Operation::ASLm): + case OpT(Operation::ASRm): + case OpT(Operation::LSLm): + case OpT(Operation::LSRm): + case OpT(Operation::ROLm): + case OpT(Operation::RORm): + case OpT(Operation::ROXLm): + case OpT(Operation::ROXRm): + return ~OneOperandMask< + Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl + >::value; + + case OpT(Operation::Bccb): case OpT(Operation::BSRb): + case OpT(Operation::TRAP): return ~OneOperandMask< Quick >::value; @@ -340,6 +367,7 @@ template uint32_t Predecoder::invalid_operands() { >::value; case OpT(Operation::EXTbtow): case OpT(Operation::EXTwtol): + case OpT(Operation::SWAP): return ~OneOperandMask< Dn >::value; @@ -347,14 +375,38 @@ template uint32_t Predecoder::invalid_operands() { case OpT(Operation::JMP): case OpT(Operation::JSR): return ~OneOperandMask< - Ind | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn + ControlAddressingModes + >::value; + + case OpT(Operation::LEA): + return ~TwoOperandMask< + ControlAddressingModes, + An + >::value; + + case OpT(Operation::LINKw): + return ~TwoOperandMask< + An, + Imm + >::value; + + case OpT(Operation::NOP): + case OpT(Operation::RTE): + case OpT(Operation::RTS): + case OpT(Operation::TRAPV): + case OpT(Operation::RTR): + return ~NoOperandMask::value; + + case OpT(Operation::UNLINK): + case OpT(Operation::MOVEtoUSP): + case OpT(Operation::MOVEfromUSP): + return ~OneOperandMask< + An >::value; } } /// Provides a post-decoding validation step — primarily ensures that the prima facie addressing modes are supported by the operation. -// TODO: once complete and working, see how ugly it would be to incorpoate these tests into the main -// decoding switches. template template Preinstruction Predecoder::validated(Preinstruction original) { if constexpr (!validate) { @@ -362,44 +414,7 @@ template Preinstruction Predecoder::validated } switch(op) { - default: return original; - - // All operations converted to the AND test. - case OpT(Operation::ABCD): - case OpT(Operation::ADDXb): case OpT(Operation::ADDXw): case OpT(Operation::ADDXl): - case ADDtoRb: case ADDtoRw: case ADDtoRl: - case ADDIb: case ADDIl: case ADDIw: - case ADDtoMb: case ADDtoMw: case ADDtoMl: - case OpT(Operation::ADDAw): case OpT(Operation::ADDAl): - case ADDQb: case ADDQw: case ADDQl: - case ANDtoRb: case ANDtoRw: case ANDtoRl: - case ANDtoMb: case ANDtoMw: case ANDtoMl: - case ANDIb: case ANDIl: case ANDIw: - case OpT(Operation::ANDItoCCR): - case OpT(Operation::ASLb): case OpT(Operation::ASLw): case OpT(Operation::ASLl): - case OpT(Operation::ASRb): case OpT(Operation::ASRw): case OpT(Operation::ASRl): - case OpT(Operation::Bccb): case OpT(Operation::Bccw): case OpT(Operation::Bccl): - case OpT(Operation::BCHG): case BCHGI: - case OpT(Operation::BCLR): case BCLRI: - case OpT(Operation::BSET): case BSETI: - case OpT(Operation::BSRb): case OpT(Operation::BSRw): case OpT(Operation::BSRl): - case OpT(Operation::BTST): case BTSTI: - case OpT(Operation::CHK): - case OpT(Operation::CLRb): case OpT(Operation::CLRw): case OpT(Operation::CLRl): - case OpT(Operation::CMPb): case OpT(Operation::CMPw): case OpT(Operation::CMPl): - case OpT(Operation::CMPAw): case OpT(Operation::CMPAl): - case CMPIb: case CMPIl: case CMPIw: - case CMPMb: case CMPMw: case CMPMl: - case OpT(Operation::DBcc): - case OpT(Operation::DIVS): case OpT(Operation::DIVU): - case OpT(Operation::EORb): case OpT(Operation::EORw): case OpT(Operation::EORl): - case EORIb: case EORIw: case EORIl: - case OpT(Operation::EORItoCCR): - case EXGRtoR: case EXGAtoA: case EXGRtoA: - case OpT(Operation::EXTbtow): case OpT(Operation::EXTwtol): - case OpT(Operation::JMP): - case OpT(Operation::JSR): - case OpT(Operation::NBCD): { + default: { const auto invalid = invalid_operands(); const auto observed = operand_mask(original); return (observed & invalid) ? Preinstruction() : original; @@ -579,7 +594,7 @@ template Preinstruction Predecoder::validated } // LEA, PEA - case OpT(Operation::LEA): case OpT(Operation::PEA): + case OpT(Operation::PEA): switch(original.mode<0>()) { default: return original; @@ -632,22 +647,6 @@ template Preinstruction Predecoder::validated return Preinstruction(); } - case OpT(Operation::ASLm): case OpT(Operation::ASRm): - case OpT(Operation::LSLm): case OpT(Operation::LSRm): - case OpT(Operation::ROLm): case OpT(Operation::RORm): - case OpT(Operation::ROXLm): case OpT(Operation::ROXRm): - switch(original.mode<0>()) { - default: return original; - - case AddressingMode::DataRegisterDirect: - case AddressingMode::AddressRegisterDirect: - case AddressingMode::ImmediateData: - case AddressingMode::ProgramCounterIndirectWithDisplacement: - case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: - case AddressingMode::None: - return Preinstruction(); - } - case MOVEMtoMw: case MOVEMtoMl: switch(original.mode<1>()) { default: return original; From 3268ea42fff8a60aac2aa2acc519e36bbd94f217 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 25 Apr 2022 12:41:41 -0400 Subject: [PATCH 16/19] Translate SUB, PEA. --- InstructionSets/68k/Decoder.cpp | 89 ++++----------------------------- 1 file changed, 11 insertions(+), 78 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index 3f6583a48..4f37527b8 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -195,6 +195,7 @@ template uint32_t Predecoder::invalid_operands() { case ANDtoRb: case ANDtoRw: case ANDtoRl: case OpT(Operation::CHK): case OpT(Operation::CMPb): + case SUBtoRb: return ~TwoOperandMask< AllModesNoAn, Dn @@ -202,6 +203,7 @@ template uint32_t Predecoder::invalid_operands() { case ADDtoRw: case ADDtoRl: case OpT(Operation::CMPw): case OpT(Operation::CMPl): + case SUBtoRw: case SUBtoRl: return ~TwoOperandMask< AllModes, Dn @@ -209,12 +211,14 @@ template uint32_t Predecoder::invalid_operands() { case ADDtoMb: case ADDtoMw: case ADDtoMl: case ANDtoMb: case ANDtoMw: case ANDtoMl: + case SUBtoMb: case SUBtoMw: case SUBtoMl: return ~TwoOperandMask< Dn, Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl >::value; case OpT(Operation::ADDAw): case OpT(Operation::ADDAl): + case OpT(Operation::SUBAw): case OpT(Operation::SUBAl): return ~TwoOperandMask< AllModes, An @@ -222,26 +226,29 @@ template uint32_t Predecoder::invalid_operands() { case ADDIb: case ADDIl: case ADDIw: case ANDIb: case ANDIl: case ANDIw: + case SUBIb: case SUBIl: case SUBIw: return ~TwoOperandMask< Imm, AlterableAddressingModesNoAn >::value; case ADDQb: + case SUBQb: return ~TwoOperandMask< Quick, AlterableAddressingModesNoAn >::value; case ADDQw: case ADDQl: + case SUBQw: case SUBQl: return ~TwoOperandMask< Quick, AlterableAddressingModes >::value; case OpT(Operation::ANDItoCCR): case OpT(Operation::ANDItoSR): - case OpT(Operation::Bccw): case OpT(Operation::Bccl): - case OpT(Operation::BSRl): case OpT(Operation::BSRw): + case OpT(Operation::Bccw): case OpT(Operation::Bccl): + case OpT(Operation::BSRl): case OpT(Operation::BSRw): case OpT(Operation::EORItoCCR): case OpT(Operation::EORItoSR): case OpT(Operation::ORItoCCR): case OpT(Operation::ORItoSR): case OpT(Operation::STOP): @@ -343,6 +350,7 @@ template uint32_t Predecoder::invalid_operands() { >::value; case OpT(Operation::DIVU): case OpT(Operation::DIVS): + case OpT(Operation::MULU): case OpT(Operation::MULS): return ~TwoOperandMask< AllModesNoAn, Dn @@ -374,6 +382,7 @@ template uint32_t Predecoder::invalid_operands() { case OpT(Operation::JMP): case OpT(Operation::JSR): + case OpT(Operation::PEA): return ~OneOperandMask< ControlAddressingModes >::value; @@ -445,7 +454,6 @@ template Preinstruction Predecoder::validated // The various immediates. case ORIb: case ORIl: case ORIw: - case SUBIb: case SUBIl: case SUBIw: switch(original.mode<1>()) { default: return original; @@ -458,7 +466,6 @@ template Preinstruction Predecoder::validated } // ADD, SUB, MOVE, MOVEA - 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::ORb): case OpT(Operation::ORw): case OpT(Operation::ORl): { @@ -493,21 +500,6 @@ template Preinstruction Predecoder::validated } } - case SUBtoRb: case SUBtoRw: case SUBtoRl: { - constexpr bool is_byte = op == ADDtoRb || op == SUBtoRb || op == SUBtoRb || op == ADDtoRb; - - switch(original.mode<0>()) { - default: return original; - case AddressingMode::AddressRegisterDirect: - if constexpr (!is_byte) { - return original; - } - [[fallthrough]]; - case AddressingMode::None: - return Preinstruction(); - } - } - case ORtoMb: case ORtoMw: case ORtoMl: switch(original.mode<1>()) { default: return original; @@ -528,42 +520,6 @@ template Preinstruction Predecoder::validated return Preinstruction(); } - case SUBtoMb: case SUBtoMw: case SUBtoMl: { - // TODO: I'm going to need get-size-by-operation elsewhere; use that here when implemented. - constexpr bool is_byte = op == ADDtoMb || op == SUBtoMb; - - switch(original.mode<0>()) { - default: break; - case AddressingMode::AddressRegisterDirect: - if constexpr (!is_byte) { - break; - } - [[fallthrough]]; - case AddressingMode::None: - return Preinstruction(); - } - - switch(original.mode<1>()) { - default: return original; - - case AddressingMode::DataRegisterDirect: - // TODO: this is per the documentation, but is it true? - if constexpr (op == ANDtoMb || op == ANDtoMw || op == ANDtoMl || op == ORtoMb || op == ORtoMw || op == ORtoMl) { - return Preinstruction(); - } - case AddressingMode::AddressRegisterDirect: - if constexpr (!is_byte) { - return original; - } - [[fallthrough]]; - case AddressingMode::ImmediateData: - case AddressingMode::ProgramCounterIndirectWithDisplacement: - case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: - case AddressingMode::None: - return Preinstruction(); - } - } - case OpT(Operation::NOTb): case OpT(Operation::NOTw): case OpT(Operation::NOTl): switch(original.mode<0>()) { default: return original; @@ -593,20 +549,6 @@ template Preinstruction Predecoder::validated return Preinstruction(); } - // LEA, PEA - case OpT(Operation::PEA): - switch(original.mode<0>()) { - default: return original; - - case AddressingMode::None: - case AddressingMode::DataRegisterDirect: - case AddressingMode::AddressRegisterDirect: - case AddressingMode::AddressRegisterIndirectWithPostincrement: - case AddressingMode::AddressRegisterIndirectWithPredecrement: - case AddressingMode::ImmediateData: - return Preinstruction(); - } - case OpT(Operation::TSTb): case OpT(Operation::TSTw): case OpT(Operation::TSTl): switch(original.mode<0>()) { default: return original; @@ -672,15 +614,6 @@ template Preinstruction Predecoder::validated case AddressingMode::None: return Preinstruction(); } - - case OpT(Operation::MULU): case OpT(Operation::MULS): - switch(original.mode<0>()) { - default: return original; - - case AddressingMode::AddressRegisterDirect: - case AddressingMode::None: - return Preinstruction(); - } } } From 5778e92e70d535ce87d48ef7b6fc1df2e8fcdaaf Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 25 Apr 2022 15:43:25 -0400 Subject: [PATCH 17/19] Adapt MOVE, DIV, MUL, OR. --- InstructionSets/68k/Decoder.cpp | 62 ++++++++++----------------------- 1 file changed, 18 insertions(+), 44 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index 4f37527b8..5fc6c2f79 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -195,6 +195,9 @@ template uint32_t Predecoder::invalid_operands() { case ANDtoRb: case ANDtoRw: case ANDtoRl: case OpT(Operation::CHK): case OpT(Operation::CMPb): + case OpT(Operation::DIVU): case OpT(Operation::DIVS): + case ORtoRb: case ORtoRw: case ORtoRl: + case OpT(Operation::MULU): case OpT(Operation::MULS): case SUBtoRb: return ~TwoOperandMask< AllModesNoAn, @@ -211,6 +214,7 @@ template uint32_t Predecoder::invalid_operands() { case ADDtoMb: case ADDtoMw: case ADDtoMl: case ANDtoMb: case ANDtoMw: case ANDtoMl: + case ORtoMb: case ORtoMw: case ORtoMl: case SUBtoMb: case SUBtoMw: case SUBtoMl: return ~TwoOperandMask< Dn, @@ -246,6 +250,18 @@ template uint32_t Predecoder::invalid_operands() { AlterableAddressingModes >::value; + case OpT(Operation::MOVEb): + return ~TwoOperandMask< + AllModesNoAn, + AlterableAddressingModesNoAn + >::value; + + case OpT(Operation::MOVEw): case OpT(Operation::MOVEl): + return ~TwoOperandMask< + AllModes, + AlterableAddressingModesNoAn + >::value; + case OpT(Operation::ANDItoCCR): case OpT(Operation::ANDItoSR): case OpT(Operation::Bccw): case OpT(Operation::Bccl): case OpT(Operation::BSRl): case OpT(Operation::BSRw): @@ -300,6 +316,7 @@ template uint32_t Predecoder::invalid_operands() { case BCHGI: case BCLRI: case BSETI: case EORIb: case EORIw: case EORIl: + case ORIb: case ORIw: case ORIl: return ~TwoOperandMask< Imm, AlterableAddressingModesNoAn @@ -349,13 +366,6 @@ template uint32_t Predecoder::invalid_operands() { Imm >::value; - case OpT(Operation::DIVU): case OpT(Operation::DIVS): - case OpT(Operation::MULU): case OpT(Operation::MULS): - return ~TwoOperandMask< - AllModesNoAn, - Dn - >::value; - case EXGRtoR: return ~TwoOperandMask< Dn, @@ -452,23 +462,7 @@ template Preinstruction Predecoder::validated return Preinstruction(); } - // The various immediates. - case ORIb: case ORIl: case ORIw: - switch(original.mode<1>()) { - default: return original; - - case AddressingMode::AddressRegisterDirect: - case AddressingMode::ImmediateData: - case AddressingMode::ProgramCounterIndirectWithDisplacement: - case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: - case AddressingMode::None: - return Preinstruction(); - } - - // ADD, SUB, MOVE, MOVEA - case OpT(Operation::MOVEb): case OpT(Operation::MOVEw): case OpT(Operation::MOVEl): - case OpT(Operation::MOVEAw): case OpT(Operation::MOVEAl): - case OpT(Operation::ORb): case OpT(Operation::ORw): case OpT(Operation::ORl): { + 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::MOVEb) || op == ADDQb || op == SUBQb || op == OpT(Operation::EORb); @@ -500,26 +494,6 @@ template Preinstruction Predecoder::validated } } - case ORtoMb: case ORtoMw: case ORtoMl: - switch(original.mode<1>()) { - default: return original; - case AddressingMode::DataRegisterDirect: - case AddressingMode::AddressRegisterDirect: - case AddressingMode::ImmediateData: - case AddressingMode::ProgramCounterIndirectWithDisplacement: - case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: - case AddressingMode::None: - return Preinstruction(); - } - - case ORtoRb: case ORtoRw: case ORtoRl: - switch(original.mode<0>()) { - default: return original; - case AddressingMode::AddressRegisterDirect: - case AddressingMode::None: - return Preinstruction(); - } - case OpT(Operation::NOTb): case OpT(Operation::NOTw): case OpT(Operation::NOTl): switch(original.mode<0>()) { default: return original; From 0c688757b0b065117c61d55977a5cda0e4579bc1 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 25 Apr 2022 16:05:44 -0400 Subject: [PATCH 18/19] Adapt the last of the MOVEs, TAS, NOT, SUB and TST. --- InstructionSets/68k/Decoder.cpp | 142 +++++++------------------------- 1 file changed, 30 insertions(+), 112 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index 5fc6c2f79..7d77d63b7 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -221,8 +221,9 @@ template uint32_t Predecoder::invalid_operands() { Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl >::value; - case OpT(Operation::ADDAw): case OpT(Operation::ADDAl): - case OpT(Operation::SUBAw): case OpT(Operation::SUBAl): + case OpT(Operation::ADDAw): case OpT(Operation::ADDAl): + case OpT(Operation::SUBAw): case OpT(Operation::SUBAl): + case OpT(Operation::MOVEAw): case OpT(Operation::MOVEAl): return ~TwoOperandMask< AllModes, An @@ -344,10 +345,37 @@ template uint32_t Predecoder::invalid_operands() { case OpT(Operation::CLRb): case OpT(Operation::CLRw): case OpT(Operation::CLRl): case OpT(Operation::NBCD): + case OpT(Operation::MOVEfromSR): + case OpT(Operation::NOTb): case OpT(Operation::NOTw): case OpT(Operation::NOTl): + case OpT(Operation::TAS): return ~OneOperandMask< AlterableAddressingModesNoAn >::value; + case OpT(Operation::TSTb): + if constexpr (model == Model::M68000) { + return ~OneOperandMask< + AlterableAddressingModesNoAn + >::value; + } + [[fallthrough]]; + case OpT(Operation::MOVEtoCCR): + case OpT(Operation::MOVEtoSR): + return ~OneOperandMask< + AllModesNoAn + >::value; + + case OpT(Operation::TSTw): case OpT(Operation::TSTl): + if constexpr (model == Model::M68000) { + return ~OneOperandMask< + AlterableAddressingModesNoAn + >::value; + } else { + return ~OneOperandMask< + AllModes + >::value; + } + case OpT(Operation::CMPAw): case OpT(Operation::CMPAl): return ~TwoOperandMask< AllModes, @@ -439,116 +467,6 @@ template Preinstruction Predecoder::validated return (observed & invalid) ? Preinstruction() : original; } - case OpT(Operation::MOVEfromSR): - case OpT(Operation::TAS): - switch(original.mode<0>()) { - default: return original; - - case AddressingMode::AddressRegisterDirect: - case AddressingMode::ProgramCounterIndirectWithDisplacement: - case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: - case AddressingMode::ImmediateData: - case AddressingMode::None: - return Preinstruction(); - } - - case OpT(Operation::MOVEtoCCR): - case OpT(Operation::MOVEtoSR): - switch(original.mode<0>()) { - default: return original; - - case AddressingMode::AddressRegisterDirect: - case AddressingMode::None: - return Preinstruction(); - } - - 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::MOVEb) || op == ADDQb || op == SUBQb || op == OpT(Operation::EORb); - - switch(original.mode<0>()) { - default: break; - case AddressingMode::AddressRegisterDirect: - if constexpr (!is_byte) { - break; - } - [[fallthrough]]; - case AddressingMode::None: - return Preinstruction(); - } - - switch(original.mode<1>()) { - default: return original; - - case AddressingMode::AddressRegisterDirect: - if constexpr (!is_byte) { - return original; - } - [[fallthrough]]; - case AddressingMode::ImmediateData: - case AddressingMode::ProgramCounterIndirectWithDisplacement: - case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: - case AddressingMode::None: - return Preinstruction(); - } - } - - case OpT(Operation::NOTb): case OpT(Operation::NOTw): case OpT(Operation::NOTl): - switch(original.mode<0>()) { - default: return original; - - case AddressingMode::AddressRegisterDirect: - case AddressingMode::ImmediateData: - case AddressingMode::ProgramCounterIndirectWithDisplacement: - case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: - case AddressingMode::None: - return Preinstruction(); - } - - case OpT(Operation::SUBAw): case OpT(Operation::SUBAl): - switch(original.mode<0>()) { - default: break; - case AddressingMode::None: - return Preinstruction(); - } - - switch(original.mode<1>()) { - default: return original; - - case AddressingMode::ImmediateData: - case AddressingMode::ProgramCounterIndirectWithDisplacement: - case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: - case AddressingMode::None: - return Preinstruction(); - } - - case OpT(Operation::TSTb): case OpT(Operation::TSTw): case OpT(Operation::TSTl): - switch(original.mode<0>()) { - default: return original; - - case AddressingMode::AddressRegisterDirect: - if constexpr (op == OpT(Operation::TSTb)) { - return Preinstruction(); - } - [[fallthrough]]; - - case AddressingMode::ImmediateData: - if constexpr (model < Model::M68020) { - return Preinstruction(); - } - return original; - - case AddressingMode::ProgramCounterIndirectWithDisplacement: - case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: - if constexpr (model >= Model::M68010) { - return original; - } - [[fallthrough]]; - case AddressingMode::None: - return Preinstruction(); - } - case OpT(Operation::Scc): case OpT(Operation::NEGXb): case OpT(Operation::NEGXw): case OpT(Operation::NEGXl): case OpT(Operation::NEGb): case OpT(Operation::NEGw): case OpT(Operation::NEGl): From 8f8f201186d766ae9817eee5a94e72f63a22f273 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 25 Apr 2022 16:23:16 -0400 Subject: [PATCH 19/19] Complete transition to simple AND-based verification. --- InstructionSets/68k/Decoder.cpp | 102 +++++++++----------------------- 1 file changed, 27 insertions(+), 75 deletions(-) diff --git a/InstructionSets/68k/Decoder.cpp b/InstructionSets/68k/Decoder.cpp index 7d77d63b7..87c3c15d3 100644 --- a/InstructionSets/68k/Decoder.cpp +++ b/InstructionSets/68k/Decoder.cpp @@ -37,12 +37,8 @@ constexpr AddressingMode combined_mode(int mode, int reg) { return modes[use_reg]; } -template struct Mask { - static constexpr uint32_t value = 0; -}; - -template struct Mask { - static constexpr uint32_t value = uint32_t(1 << int(F)) | Mask::value; +template struct Mask { + static constexpr uint32_t value = uint32_t(1 << int(F)); }; static constexpr uint32_t NoOperand = Mask::value; @@ -160,7 +156,6 @@ template uint32_t Predecoder::invalid_operands() { constexpr auto Imm = Mask< AddressingMode::ImmediateData >::value; constexpr auto Quick = Mask< AddressingMode::Quick >::value; - // A few recurring combinations; terminology is directly from // the Programmers' Reference Manual. @@ -195,9 +190,9 @@ template uint32_t Predecoder::invalid_operands() { case ANDtoRb: case ANDtoRw: case ANDtoRl: case OpT(Operation::CHK): case OpT(Operation::CMPb): - case OpT(Operation::DIVU): case OpT(Operation::DIVS): + case OpT(Operation::DIVU): case OpT(Operation::DIVS): case ORtoRb: case ORtoRw: case ORtoRl: - case OpT(Operation::MULU): case OpT(Operation::MULS): + case OpT(Operation::MULU): case OpT(Operation::MULS): case SUBtoRb: return ~TwoOperandMask< AllModesNoAn, @@ -222,6 +217,7 @@ template uint32_t Predecoder::invalid_operands() { >::value; case OpT(Operation::ADDAw): case OpT(Operation::ADDAl): + case OpT(Operation::CMPAw): case OpT(Operation::CMPAl): case OpT(Operation::SUBAw): case OpT(Operation::SUBAl): case OpT(Operation::MOVEAw): case OpT(Operation::MOVEAl): return ~TwoOperandMask< @@ -231,6 +227,9 @@ template uint32_t Predecoder::invalid_operands() { case ADDIb: case ADDIl: case ADDIw: case ANDIb: case ANDIl: case ANDIw: + case BCHGI: case BCLRI: case BSETI: + case EORIb: case EORIw: case EORIl: + case ORIb: case ORIw: case ORIl: case SUBIb: case SUBIl: case SUBIw: return ~TwoOperandMask< Imm, @@ -298,7 +297,6 @@ template uint32_t Predecoder::invalid_operands() { Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl >::value; - case OpT(Operation::Bccb): case OpT(Operation::BSRb): case OpT(Operation::TRAP): @@ -315,14 +313,6 @@ template uint32_t Predecoder::invalid_operands() { AlterableAddressingModesNoAn >::value; - case BCHGI: case BCLRI: case BSETI: - case EORIb: case EORIw: case EORIl: - case ORIb: case ORIw: case ORIl: - return ~TwoOperandMask< - Imm, - AlterableAddressingModesNoAn - >::value; - case OpT(Operation::BTST): return ~TwoOperandMask< Dn, @@ -346,7 +336,10 @@ template uint32_t Predecoder::invalid_operands() { case OpT(Operation::CLRb): case OpT(Operation::CLRw): case OpT(Operation::CLRl): case OpT(Operation::NBCD): case OpT(Operation::MOVEfromSR): - case OpT(Operation::NOTb): case OpT(Operation::NOTw): case OpT(Operation::NOTl): + case OpT(Operation::NEGXb): case OpT(Operation::NEGXw): case OpT(Operation::NEGXl): + case OpT(Operation::NEGb): case OpT(Operation::NEGw): case OpT(Operation::NEGl): + case OpT(Operation::NOTb): case OpT(Operation::NOTw): case OpT(Operation::NOTl): + case OpT(Operation::Scc): case OpT(Operation::TAS): return ~OneOperandMask< AlterableAddressingModesNoAn @@ -376,12 +369,6 @@ template uint32_t Predecoder::invalid_operands() { >::value; } - case OpT(Operation::CMPAw): case OpT(Operation::CMPAl): - return ~TwoOperandMask< - AllModes, - An - >::value; - case CMPMb: case CMPMw: case CMPMl: return ~TwoOperandMask< PostInc, @@ -450,6 +437,18 @@ template uint32_t Predecoder::invalid_operands() { return ~OneOperandMask< An >::value; + + case MOVEMtoMw: case MOVEMtoMl: + return ~TwoOperandMask< + Imm, + Ind | PreDec | d16An | d8AnXn | XXXw | XXXl + >::value; + + case MOVEMtoRw: case MOVEMtoRl: + return ~TwoOperandMask< + Ind | PostInc | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn, + Imm + >::value; } } @@ -460,53 +459,9 @@ template Preinstruction Predecoder::validated return original; } - switch(op) { - default: { - const auto invalid = invalid_operands(); - const auto observed = operand_mask(original); - return (observed & invalid) ? Preinstruction() : original; - } - - case OpT(Operation::Scc): - case OpT(Operation::NEGXb): case OpT(Operation::NEGXw): case OpT(Operation::NEGXl): - case OpT(Operation::NEGb): case OpT(Operation::NEGw): case OpT(Operation::NEGl): - switch(original.mode<0>()) { - default: return original; - - case AddressingMode::AddressRegisterDirect: - case AddressingMode::ImmediateData: - case AddressingMode::ProgramCounterIndirectWithDisplacement: - case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: - case AddressingMode::None: - return Preinstruction(); - } - - case MOVEMtoMw: case MOVEMtoMl: - switch(original.mode<1>()) { - default: return original; - - case AddressingMode::DataRegisterDirect: - case AddressingMode::AddressRegisterDirect: - case AddressingMode::AddressRegisterIndirectWithPostincrement: - case AddressingMode::ImmediateData: - case AddressingMode::ProgramCounterIndirectWithDisplacement: - case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: - case AddressingMode::None: - return Preinstruction(); - } - - case MOVEMtoRw: case MOVEMtoRl: - switch(original.mode<0>()) { - default: return original; - - case AddressingMode::DataRegisterDirect: - case AddressingMode::AddressRegisterDirect: - case AddressingMode::AddressRegisterIndirectWithPredecrement: - case AddressingMode::ImmediateData: - case AddressingMode::None: - return Preinstruction(); - } - } + const auto invalid = invalid_operands(); + const auto observed = operand_mask(original); + return (observed & invalid) ? Preinstruction() : original; } /// Decodes the fields within an instruction and constructs a `Preinstruction`, given that the operation has already been @@ -552,9 +507,6 @@ template Preinstruction Predecoder::decode(ui // b0–b2 and b3–b5: an effective address; // b6–b8: an opmode, i.e. source + direction. // - - - case ADDtoRb: case ADDtoRw: case ADDtoRl: case SUBtoRb: case SUBtoRw: case SUBtoRl: case ANDtoRb: case ANDtoRw: case ANDtoRl: