diff --git a/InstructionSets/M68k/Decoder.cpp b/InstructionSets/M68k/Decoder.cpp index 35ac44cfd..aa20d8adc 100644 --- a/InstructionSets/M68k/Decoder.cpp +++ b/InstructionSets/M68k/Decoder.cpp @@ -154,6 +154,7 @@ template uint32_t Predecoder::invalid_operands() { constexpr auto d8PCXn = Mask< AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement >::value; constexpr auto Imm = Mask< AddressingMode::ImmediateData >::value; constexpr auto Quick = Mask< AddressingMode::Quick >::value; + constexpr auto Ext = Mask< AddressingMode::ExtensionWord >::value; // A few recurring combinations; terminology is directly from // the Programmers' Reference Manual. @@ -191,11 +192,11 @@ template uint32_t Predecoder::invalid_operands() { case ADDtoRb: case ANDtoRb: case ANDtoRw: case ANDtoRl: - case OpT(Operation::CHK): + case OpT(Operation::CHKw): case OpT(Operation::CMPb): - case OpT(Operation::DIVU): case OpT(Operation::DIVS): + case OpT(Operation::DIVUw): case OpT(Operation::DIVSw): case ORtoRb: case ORtoRw: case ORtoRl: - case OpT(Operation::MULU): case OpT(Operation::MULS): + case OpT(Operation::MULUw): case OpT(Operation::MULSw): case SUBtoRb: return ~TwoOperandMask< AllModesNoAn, @@ -473,6 +474,11 @@ template uint32_t Predecoder::invalid_operands() { case OpT(Operation::RESET): return ~NoOperandMask::value; + case OpT(Operation::RTM): + return ~OneOperandMask< + An | Dn + >::value; + case OpT(Operation::UNLINK): case OpT(Operation::MOVEtoUSP): case OpT(Operation::MOVEfromUSP): @@ -482,13 +488,13 @@ template uint32_t Predecoder::invalid_operands() { case OpT(Operation::MOVEMtoMw): case OpT(Operation::MOVEMtoMl): return ~TwoOperandMask< - Imm, + Ext, Ind | PreDec | d16An | d8AnXn | XXXw | XXXl >::value; case OpT(Operation::MOVEMtoRw): case OpT(Operation::MOVEMtoRl): return ~TwoOperandMask< - Imm, + Ext, Ind | PostInc | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn >::value; @@ -664,7 +670,7 @@ template Preinstruction Predecoder::decode(ui // Implicitly: destination is a register; // b0–b2 and b3–b5: source effective address. // - case OpT(Operation::CHK): + case OpT(Operation::CHKw): return validated( combined_mode(ea_mode, ea_register), ea_register, AddressingMode::DataRegisterDirect, data_register); @@ -697,12 +703,23 @@ template Preinstruction Predecoder::decode(ui // b9–b11: destination data register; // b0–b2 and b3–b5: source effective address. // - case OpT(Operation::DIVU): case OpT(Operation::DIVS): - case OpT(Operation::MULU): case OpT(Operation::MULS): + case OpT(Operation::DIVUw): case OpT(Operation::DIVSw): + case OpT(Operation::MULUw): case OpT(Operation::MULSw): return validated( combined_mode(ea_mode, ea_register), ea_register, AddressingMode::DataRegisterDirect, data_register); + // + // MARK: DIVSl. + // + // b0–b2 and b3–b5: source effective address. + // Plus an immediate word operand + // + case OpT(Operation::DIVSl): + return validated( + AddressingMode::ExtensionWord, 0, + combined_mode(ea_mode, ea_register), ea_register); + // // MARK: LEA // @@ -823,7 +840,7 @@ template Preinstruction Predecoder::decode(ui case OpT(Operation::MOVEMtoMl): case OpT(Operation::MOVEMtoMw): case OpT(Operation::MOVEMtoRl): case OpT(Operation::MOVEMtoRw): return validated( - AddressingMode::ImmediateData, 0, + AddressingMode::ExtensionWord, 0, combined_mode(ea_mode, ea_register), ea_register); // @@ -943,6 +960,24 @@ template Preinstruction Predecoder::decode(ui case OpT(Operation::RTD): return validated(AddressingMode::ImmediateData); + // + // MARK: RTM + // + // b0–b2: a register number; + // b3: address/data register selection. + // + case OpT(Operation::RTM): { + const auto addressing_mode = (instruction & 8) ? + AddressingMode::AddressRegisterDirect : AddressingMode::DataRegisterDirect; + + return validated(addressing_mode, ea_register); + } + + // + // MARK: DIVl + // + // + // // MARK: Impossible error case. // @@ -969,6 +1004,16 @@ Preinstruction Predecoder::decode0(uint16_t instruction) { case 0xa3c: Decode(Op::EORItoCCR); // 4-104 (p208) case 0xa7c: Decode(Op::EORItoSR); // 6-10 (p464) + // 4-68 (p172) + case 0xcfc: DecodeReq(model >= Model::M68020, Op::CAS2w); + case 0xefc: DecodeReq(model >= Model::M68020, Op::CAS2l); + + default: break; + } + + switch(instruction & 0xff0) { + case 0x6c0: DecodeReq(model == Model::M68020, Op::RTM); // 4-167 (p271) + default: break; } @@ -1015,7 +1060,23 @@ Preinstruction Predecoder::decode0(uint16_t instruction) { case 0xc40: Decode(CMPIw); case 0xc80: Decode(CMPIl); - case 0x6c0: DecodeReq(model == Model::M68020, Op::CALLM); // 4-64 (p168) + // 4-64 (p168) + case 0x6c0: DecodeReq(model == Model::M68020, Op::CALLM); + + // 4-67 (p171) + case 0xac0: DecodeReq(model >= Model::M68020, Op::CASb); + case 0xcc0: DecodeReq(model >= Model::M68020, Op::CASw); + case 0xec0: DecodeReq(model >= Model::M68020, Op::CASl); + + // 4-72 (p176) + case 0x0c0: DecodeReq(model >= Model::M68020, Op::CHK2b); + case 0x2c0: DecodeReq(model >= Model::M68020, Op::CHK2w); + case 0x4c0: DecodeReq(model >= Model::M68020, Op::CHK2l); + + // 4-83 (p187) + case 0x00c: DecodeReq(model >= Model::M68020, Op::CMP2b); + case 0x02c: DecodeReq(model >= Model::M68020, Op::CMP2w); + case 0x04c: DecodeReq(model >= Model::M68020, Op::CMP2l); default: break; } @@ -1163,12 +1224,15 @@ Preinstruction Predecoder::decode4(uint16_t instruction) { // 4-108 (p212) case 0xec0: Decode(Op::JMP); + // 4-94 (p198) + case 0xc40: Decode(Op::DIVSl); + default: break; } switch(instruction & 0x1c0) { case 0x1c0: Decode(Op::LEA); // 4-110 (p214) - case 0x180: Decode(Op::CHK); // 4-69 (p173) + case 0x180: Decode(Op::CHKw); // 4-69 (p173) default: break; } @@ -1292,8 +1356,8 @@ Preinstruction Predecoder::decode8(uint16_t instruction) { if((instruction & 0x1f0) == 0x100) Decode(Op::SBCD); switch(instruction & 0x1c0) { - case 0x0c0: Decode(Op::DIVU); // 4-97 (p201) - case 0x1c0: Decode(Op::DIVS); // 4-93 (p197) + case 0x0c0: Decode(Op::DIVUw); // 4-97 (p201) + case 0x1c0: Decode(Op::DIVSw); // 4-93 (p197) // 4-150 (p254) case 0x000: Decode(ORtoRb); @@ -1398,8 +1462,8 @@ Preinstruction Predecoder::decodeC(uint16_t instruction) { } switch(instruction & 0x1c0) { - case 0x0c0: Decode(Op::MULU); // 4-139 (p243) - case 0x1c0: Decode(Op::MULS); // 4-136 (p240) + case 0x0c0: Decode(Op::MULUw); // 4-139 (p243) + case 0x1c0: Decode(Op::MULSw); // 4-136 (p240) // 4-15 (p119) case 0x000: Decode(ANDtoRb); diff --git a/InstructionSets/M68k/Implementation/InstructionOperandFlags.hpp b/InstructionSets/M68k/Implementation/InstructionOperandFlags.hpp index ca29cc574..cc186ebe1 100644 --- a/InstructionSets/M68k/Implementation/InstructionOperandFlags.hpp +++ b/InstructionSets/M68k/Implementation/InstructionOperandFlags.hpp @@ -81,7 +81,7 @@ template constexpr uint8_t operand_flags(Op // case Operation::CMPb: case Operation::CMPw: case Operation::CMPl: case Operation::CMPAw: case Operation::CMPAl: - case Operation::CHK: + case Operation::CHKw: case Operation::BTST: case Operation::LINKw: return FetchOp1 | FetchOp2; @@ -106,8 +106,8 @@ template constexpr uint8_t operand_flags(Op case Operation::ORb: case Operation::ORw: case Operation::ORl: case Operation::ANDb: case Operation::ANDw: case Operation::ANDl: case Operation::EORb: case Operation::EORw: case Operation::EORl: - case Operation::DIVU: case Operation::DIVS: - case Operation::MULU: case Operation::MULS: + case Operation::DIVUw: case Operation::DIVSw: + case Operation::MULUw: case Operation::MULSw: case Operation::ASLb: case Operation::ASLw: case Operation::ASLl: case Operation::ASRb: case Operation::ASRw: case Operation::ASRl: case Operation::LSLb: case Operation::LSLw: case Operation::LSLl: diff --git a/InstructionSets/M68k/Implementation/InstructionOperandSize.hpp b/InstructionSets/M68k/Implementation/InstructionOperandSize.hpp index ff3f07b53..47380ec10 100644 --- a/InstructionSets/M68k/Implementation/InstructionOperandSize.hpp +++ b/InstructionSets/M68k/Implementation/InstructionOperandSize.hpp @@ -80,11 +80,11 @@ constexpr DataSize operand_size(Operation r_operation) { case Operation::MOVEPw: case Operation::ANDw: case Operation::EORw: case Operation::NOTw: case Operation::ORw: - case Operation::DIVU: case Operation::DIVS: - case Operation::MULU: case Operation::MULS: + case Operation::DIVUw: case Operation::DIVSw: + case Operation::MULUw: case Operation::MULSw: case Operation::EXTbtow: case Operation::LINKw: - case Operation::CHK: + case Operation::CHKw: return DataSize::Word; case Operation::ADDl: case Operation::ADDAl: diff --git a/InstructionSets/M68k/Implementation/PerformImplementation.hpp b/InstructionSets/M68k/Implementation/PerformImplementation.hpp index 2043cbd9c..2291ef6b1 100644 --- a/InstructionSets/M68k/Implementation/PerformImplementation.hpp +++ b/InstructionSets/M68k/Implementation/PerformImplementation.hpp @@ -742,15 +742,15 @@ template < Multiplications. */ - case Operation::MULU: Primitive::multiply(src.w, dest.l, status, flow_controller); break; - case Operation::MULS: Primitive::multiply(src.w, dest.l, status, flow_controller); break; + case Operation::MULUw: Primitive::multiply(src.w, dest.l, status, flow_controller); break; + case Operation::MULSw: Primitive::multiply(src.w, dest.l, status, flow_controller); break; /* Divisions. */ - case Operation::DIVU: Primitive::divide(src.w, dest.l, status, flow_controller); break; - case Operation::DIVS: Primitive::divide(src.w, dest.l, status, flow_controller); break; + case Operation::DIVUw: Primitive::divide(src.w, dest.l, status, flow_controller); break; + case Operation::DIVSw: Primitive::divide(src.w, dest.l, status, flow_controller); break; // TRAP, which is a nicer form of ILLEGAL. case Operation::TRAP: @@ -763,7 +763,7 @@ template < } } break; - case Operation::CHK: { + case Operation::CHKw: { const bool is_under = s_extend16(dest.w) < 0; const bool is_over = s_extend16(dest.w) > s_extend16(src.w); diff --git a/InstructionSets/M68k/Instruction.cpp b/InstructionSets/M68k/Instruction.cpp index dfd09c4fd..c3cc5cc78 100644 --- a/InstructionSets/M68k/Instruction.cpp +++ b/InstructionSets/M68k/Instruction.cpp @@ -217,17 +217,17 @@ const char *_to_string(Operation operation, bool is_quick) { case Operation::ORw: return "OR.w"; case Operation::ORl: return "OR.l"; - case Operation::MULU: return "MULU"; - case Operation::MULS: return "MULS"; - case Operation::DIVU: return "DIVU"; - case Operation::DIVS: return "DIVS"; + case Operation::MULUw: return "MULU"; + case Operation::MULSw: return "MULS"; + case Operation::DIVUw: return "DIVU"; + case Operation::DIVSw: return "DIVS"; case Operation::RTE: return "RTE"; case Operation::RTR: return "RTR"; case Operation::TRAP: return "TRAP"; case Operation::TRAPV: return "TRAPV"; - case Operation::CHK: return "CHK"; + case Operation::CHKw: return "CHK"; case Operation::EXG: return "EXG"; case Operation::SWAP: return "SWAP"; diff --git a/InstructionSets/M68k/Instruction.hpp b/InstructionSets/M68k/Instruction.hpp index 1ef7cf7cf..a0a08abb5 100644 --- a/InstructionSets/M68k/Instruction.hpp +++ b/InstructionSets/M68k/Instruction.hpp @@ -61,8 +61,8 @@ enum class Operation: uint8_t { DBcc, Scc, - Bccb, Bccw, Bccl, - BSRb, BSRw, BSRl, + Bccb, Bccw, + BSRb, BSRw, CLRb, CLRw, CLRl, NEGXb, NEGXw, NEGXl, @@ -87,13 +87,13 @@ enum class Operation: uint8_t { NOTb, NOTw, NOTl, ORb, ORw, ORl, - MULU, MULS, - DIVU, DIVS, + MULUw, MULSw, + DIVUw, DIVSw, RTE, RTR, TRAP, TRAPV, - CHK, + CHKw, EXG, SWAP, @@ -108,23 +108,30 @@ enum class Operation: uint8_t { // // 68020 additions. // - BKPT, + BKPT, TRAPcc, + + CALLM, RTD, RTM, BFCHG, BFCLR, BFEXTS, BFEXTU, BFFFO, BFINS, BFSET, BFTST, - CALLM, RTD, RTM, + PACK, UNPK, - CAS, CAS2, - CHK2, CMP2, + CASb, CASw, CASl, + CAS2w, CAS2l, + + CHK2b, CHK2w, CHK2l, + CMP2b, CMP2w, CMP2l, + + DIVSl, DIVUl, + MULSl, MULUl, + + Bccl, BSRl, + LINKl, CHKl, - DIVSL, EXTbtol, - PACK, UNPK, - - TRAPcc, cpBcc, cpDBcc, cpGEN, cpScc, cpTRAPcc, cpRESTORE, @@ -285,6 +292,10 @@ enum class AddressingMode: uint8_t { /// # ImmediateData = 0b01'100, + /// An additional word of data. Differs from ImmediateData by being + /// a fixed size, rather than the @c operand_size of the operation. + ExtensionWord = 0b01'111, + /// .q; value is embedded in the opcode. Quick = 0b01'110, }; diff --git a/OSBindings/Mac/Clock SignalTests/68000ComparativeTests.mm b/OSBindings/Mac/Clock SignalTests/68000ComparativeTests.mm index 94c6cddce..374df93ff 100644 --- a/OSBindings/Mac/Clock SignalTests/68000ComparativeTests.mm +++ b/OSBindings/Mac/Clock SignalTests/68000ComparativeTests.mm @@ -438,8 +438,8 @@ struct TestProcessor: public CPU::MC68000Mk2::BusHandler { // For DIVU and DIVS, for now, test only the well-defined flags. if( - instruction.operation != InstructionSet::M68k::Operation::DIVS && - instruction.operation != InstructionSet::M68k::Operation::DIVU + instruction.operation != InstructionSet::M68k::Operation::DIVSw && + instruction.operation != InstructionSet::M68k::Operation::DIVUw ) { [_failures addObject:name]; } else { diff --git a/OSBindings/Mac/Clock SignalTests/68000OldVsNew.mm b/OSBindings/Mac/Clock SignalTests/68000OldVsNew.mm index 6d0655f2e..130914ccc 100644 --- a/OSBindings/Mac/Clock SignalTests/68000OldVsNew.mm +++ b/OSBindings/Mac/Clock SignalTests/68000OldVsNew.mm @@ -540,17 +540,17 @@ void print_transactions(FILE *target, const std::vector &transactio InstructionSet::M68k::Operation::NOTw, // Old implementation omits an idle cycle before -(An) InstructionSet::M68k::Operation::TRAP, // Old implementation relocates the idle state near the end to the beginning. InstructionSet::M68k::Operation::TRAPV, // Old implementation relocates the idle state near the end to the beginning. - InstructionSet::M68k::Operation::CHK, // Old implementation pauses four cycles too long. + InstructionSet::M68k::Operation::CHKw, // Old implementation pauses four cycles too long. InstructionSet::M68k::Operation::TAS, // Old implementation just doesn't match published cycle counts. // // Operations with timing discrepancies between the two 68000 implementations // that I think are _more_ accurate now, but possibly still need work: // - InstructionSet::M68k::Operation::MULU, - InstructionSet::M68k::Operation::MULS, - InstructionSet::M68k::Operation::DIVU, - InstructionSet::M68k::Operation::DIVS, + InstructionSet::M68k::Operation::MULUw, + InstructionSet::M68k::Operation::MULSw, + InstructionSet::M68k::Operation::DIVUw, + InstructionSet::M68k::Operation::DIVSw, }; int testsRun = 0; diff --git a/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp b/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp index 7c1585b62..df4358df0 100644 --- a/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp +++ b/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp @@ -826,7 +826,7 @@ void Processor