// // Instruction.cpp // Clock Signal // // Created by Thomas Harte on 12/05/2022. // Copyright © 2022 Thomas Harte. All rights reserved. // #include "Instruction.hpp" #include using namespace InstructionSet::M68k; std::string Preinstruction::operand_description(int index, int opcode) const { switch(mode(index)) { default: assert(false); case AddressingMode::None: return ""; case AddressingMode::DataRegisterDirect: return std::string("D") + std::to_string(reg(index)); case AddressingMode::AddressRegisterDirect: return std::string("A") + std::to_string(reg(index)); case AddressingMode::AddressRegisterIndirect: return std::string("(A") + std::to_string(reg(index)) + ")"; case AddressingMode::AddressRegisterIndirectWithPostincrement: return std::string("(A") + std::to_string(reg(index)) + ")+"; case AddressingMode::AddressRegisterIndirectWithPredecrement: return std::string("-(A") + std::to_string(reg(index)) + ")"; case AddressingMode::AddressRegisterIndirectWithDisplacement: return std::string("(d16, A") + std::to_string(reg(index)) + ")"; case AddressingMode::AddressRegisterIndirectWithIndex8bitDisplacement: return std::string("(d8, A") + std::to_string(reg(index)) + ", Xn)"; case AddressingMode::ProgramCounterIndirectWithDisplacement: return "(d16, PC)"; case AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement: return "(d8, PC, Xn)"; case AddressingMode::AbsoluteShort: return "(xxx).w"; case AddressingMode::AbsoluteLong: return "(xxx).l"; case AddressingMode::ExtensionWord: case AddressingMode::ImmediateData: return "#"; case AddressingMode::Quick: if(opcode == -1) { return "Q"; } return std::to_string(int(quick(uint16_t(opcode), operation))); } } namespace { const char *_to_string(Operation operation, bool is_quick) { switch(operation) { case Operation::Undefined: return "None"; case Operation::NOP: return "NOP"; case Operation::ABCD: return "ABCD"; case Operation::SBCD: return "SBCD"; case Operation::NBCD: return "NBCD"; case Operation::ADDb: return "ADD.b"; case Operation::ADDw: return "ADD.w"; case Operation::ADDl: return "ADD.l"; case Operation::ADDAw: return is_quick ? "ADD.w" : "ADDA.w"; case Operation::ADDAl: return is_quick ? "ADD.l" : "ADDA.l"; case Operation::ADDXb: return "ADDX.b"; case Operation::ADDXw: return "ADDX.w"; case Operation::ADDXl: return "ADDX.l"; case Operation::SUBb: return "SUB.b"; case Operation::SUBw: return "SUB.w"; case Operation::SUBl: return "SUB.l"; case Operation::SUBAw: return is_quick ? "SUB.w" : "SUBA.w"; case Operation::SUBAl: return is_quick ? "SUB.l" : "SUBA.l"; case Operation::SUBXb: return "SUBX.b"; case Operation::SUBXw: return "SUBX.w"; case Operation::SUBXl: return "SUBX.l"; case Operation::MOVEb: return "MOVE.b"; case Operation::MOVEw: return "MOVE.w"; case Operation::MOVEl: return is_quick ? "MOVE.q" : "MOVE.l"; case Operation::MOVEAw: return "MOVEA.w"; case Operation::MOVEAl: return "MOVEA.l"; case Operation::MOVESb: return "MOVES.b"; case Operation::MOVESw: return "MOVES.w"; case Operation::MOVESl: return "MOVES.l"; case Operation::LEA: return "LEA"; case Operation::PEA: return "PEA"; case Operation::MOVEtoSR: return "MOVEtoSR"; case Operation::MOVEfromSR: return "MOVEfromSR"; case Operation::MOVEtoCCR: return "MOVEtoCCR"; case Operation::MOVEfromCCR: return "MOVEfromCCR"; case Operation::MOVEtoUSP: return "MOVEtoUSP"; case Operation::MOVEfromUSP: return "MOVEfromUSP"; case Operation::MOVEtoC: return "MOVEtoC"; case Operation::MOVEfromC: return "MOVEfromC"; case Operation::ORItoSR: return "ORItoSR"; case Operation::ORItoCCR: return "ORItoCCR"; case Operation::ANDItoSR: return "ANDItoSR"; case Operation::ANDItoCCR: return "ANDItoCCR"; case Operation::EORItoSR: return "EORItoSR"; case Operation::EORItoCCR: return "EORItoCCR"; case Operation::BTST: return "BTST"; case Operation::BCLR: return "BCLR"; case Operation::BCHG: return "BCHG"; case Operation::BSET: return "BSET"; case Operation::CMPb: return "CMP.b"; case Operation::CMPw: return "CMP.w"; case Operation::CMPl: return "CMP.l"; case Operation::CMPAw: return "CMPA.w"; case Operation::CMPAl: return "CMPA.l"; case Operation::TSTb: return "TST.b"; case Operation::TSTw: return "TST.w"; case Operation::TSTl: return "TST.l"; case Operation::JMP: return "JMP"; case Operation::JSR: return "JSR"; case Operation::RTS: return "RTS"; case Operation::RTD: return "RTD"; case Operation::RTM: return "RTM"; case Operation::DBcc: return "DBcc"; case Operation::Scc: return "Scc"; case Operation::TRAPcc: return "TRAPcc"; case Operation::Bccb: case Operation::Bccl: case Operation::Bccw: return "Bcc"; case Operation::BSRb: case Operation::BSRl: case Operation::BSRw: return "BSR"; case Operation::CASb: return "CAS.b"; case Operation::CASw: return "CAS.w"; case Operation::CASl: return "CAS.l"; case Operation::CAS2w: return "CAS2.w"; case Operation::CAS2l: return "CAS2.l"; case Operation::CLRb: return "CLR.b"; case Operation::CLRw: return "CLR.w"; case Operation::CLRl: return "CLR.l"; case Operation::NEGXb: return "NEGX.b"; case Operation::NEGXw: return "NEGX.w"; case Operation::NEGXl: return "NEGX.l"; case Operation::NEGb: return "NEG.b"; case Operation::NEGw: return "NEG.w"; case Operation::NEGl: return "NEG.l"; case Operation::ASLb: return "ASL.b"; case Operation::ASLw: return "ASL.w"; case Operation::ASLl: return "ASL.l"; case Operation::ASLm: return "ASL.w"; case Operation::ASRb: return "ASR.b"; case Operation::ASRw: return "ASR.w"; case Operation::ASRl: return "ASR.l"; case Operation::ASRm: return "ASR.w"; case Operation::LSLb: return "LSL.b"; case Operation::LSLw: return "LSL.w"; case Operation::LSLl: return "LSL.l"; case Operation::LSLm: return "LSL.w"; case Operation::LSRb: return "LSR.b"; case Operation::LSRw: return "LSR.w"; case Operation::LSRl: return "LSR.l"; case Operation::LSRm: return "LSR.w"; case Operation::ROLb: return "ROL.b"; case Operation::ROLw: return "ROL.w"; case Operation::ROLl: return "ROL.l"; case Operation::ROLm: return "ROL.w"; case Operation::RORb: return "ROR.b"; case Operation::RORw: return "ROR.w"; case Operation::RORl: return "ROR.l"; case Operation::RORm: return "ROR.w"; case Operation::ROXLb: return "ROXL.b"; case Operation::ROXLw: return "ROXL.w"; case Operation::ROXLl: return "ROXL.l"; case Operation::ROXLm: return "ROXL.w"; case Operation::ROXRb: return "ROXR.b"; case Operation::ROXRw: return "ROXR.w"; case Operation::ROXRl: return "ROXR.l"; case Operation::ROXRm: return "ROXR.w"; case Operation::MOVEMtoMl: return "MOVEM.l"; case Operation::MOVEMtoMw: return "MOVEM.w"; case Operation::MOVEMtoRl: return "MOVEM.l"; case Operation::MOVEMtoRw: return "MOVEM.w"; case Operation::MOVEPl: return "MOVEP.l"; case Operation::MOVEPw: return "MOVEP.w"; case Operation::ANDb: return "AND.b"; case Operation::ANDw: return "AND.w"; case Operation::ANDl: return "AND.l"; case Operation::EORb: return "EOR.b"; case Operation::EORw: return "EOR.w"; case Operation::EORl: return "EOR.l"; case Operation::NOTb: return "NOT.b"; case Operation::NOTw: return "NOT.w"; case Operation::NOTl: return "NOT.l"; case Operation::ORb: return "OR.b"; case Operation::ORw: return "OR.w"; case Operation::ORl: return "OR.l"; case Operation::MULUw: return "MULU"; case Operation::MULSw: return "MULS"; case Operation::MULSorMULUl: return "[MULS/MULU]{L}.l"; case Operation::DIVUw: return "DIVU"; case Operation::DIVSw: return "DIVS"; case Operation::DIVSorDIVUl: return "[DIVS/DIVU]{L}.l"; case Operation::RTE: return "RTE"; case Operation::RTR: return "RTR"; case Operation::TRAP: return "TRAP"; case Operation::TRAPV: return "TRAPV"; case Operation::CHKw: return "CHK"; case Operation::CHKl: return "CHK.l"; case Operation::CHKorCMP2b: return "[CHK/CMP]2.b"; case Operation::CHKorCMP2w: return "[CHK/CMP]2.w"; case Operation::CHKorCMP2l: return "[CHK/CMP]2.l"; case Operation::EXG: return "EXG"; case Operation::SWAP: return "SWAP"; case Operation::TAS: return "TAS"; case Operation::EXTbtow: return "EXT.w"; case Operation::EXTwtol: return "EXT.l"; case Operation::EXTbtol: return "EXTB.l"; case Operation::LINKw: return "LINK"; case Operation::LINKl: return "LINK.l"; case Operation::UNLINK: return "UNLINK"; case Operation::STOP: return "STOP"; case Operation::RESET: return "RESET"; case Operation::BKPT: return "BKPT"; case Operation::BFCHG: return "BFCHG"; case Operation::BFCLR: return "BFCLR"; case Operation::BFEXTS: return "BFEXTS"; case Operation::BFEXTU: return "BFEXTU"; case Operation::BFFFO: return "BFFFO"; case Operation::BFINS: return "BFINS"; case Operation::BFSET: return "BFSET"; case Operation::BFTST: return "BFTST"; case Operation::PACK: return "PACK"; case Operation::UNPK: return "UNPK"; default: assert(false); return "???"; } } } const char *InstructionSet::M68k::to_string(Operation operation) { return _to_string(operation, false); } std::string Preinstruction::to_string(int opcode) const { if(operation == Operation::Undefined) return "None"; const char *const instruction = _to_string(operation, mode<0>() == AddressingMode::Quick); const bool flip_operands = (operation == Operation::MOVEMtoRl) || (operation == Operation::MOVEMtoRw); const std::string operand1 = operand_description(0 ^ int(flip_operands), opcode); const std::string operand2 = operand_description(1 ^ int(flip_operands), opcode); std::string result = instruction; if(!operand1.empty()) result += std::string(" ") + operand1; if(!operand2.empty()) result += std::string(", ") + operand2; const int extension_words = additional_extension_words(); if(extension_words) result += std::string(" [+") + std::to_string(extension_words) + "]"; return result; } const char *Preinstruction::operation_string() const { return _to_string(operation, mode<0>() == AddressingMode::Quick); }