mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 23:52:26 +00:00
Merge pull request #1021 from TomHarte/68kDecoder
Establishes a formal 68k [pre-]decoder.
This commit is contained in:
commit
649fe7a1ec
1424
InstructionSets/M68k/Decoder.cpp
Normal file
1424
InstructionSets/M68k/Decoder.cpp
Normal file
File diff suppressed because it is too large
Load Diff
115
InstructionSets/M68k/Decoder.hpp
Normal file
115
InstructionSets/M68k/Decoder.hpp
Normal file
@ -0,0 +1,115 @@
|
||||
//
|
||||
// Decoder.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 10/04/2022.
|
||||
// Copyright © 2022 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef InstructionSets_M68k_Decoder_hpp
|
||||
#define InstructionSets_M68k_Decoder_hpp
|
||||
|
||||
#include "Instruction.hpp"
|
||||
#include "Model.hpp"
|
||||
|
||||
namespace InstructionSet {
|
||||
namespace M68k {
|
||||
|
||||
/*!
|
||||
A stateless decoder that can map from instruction words to preinstructions
|
||||
(i.e. enough to know the operation and size, and either know the addressing mode
|
||||
and registers or else know how many further extension words are needed).
|
||||
|
||||
WARNING: at present this handles the original 68000 instruction set only. It
|
||||
requires a model only for the sake of not baking in assumptions about MOVE SR, etc,
|
||||
and supporting extended addressing modes in some cases.
|
||||
|
||||
But it does not yet decode any operations which were not present on the 68000.
|
||||
*/
|
||||
template <Model model> class Predecoder {
|
||||
public:
|
||||
Preinstruction decode(uint16_t instruction);
|
||||
|
||||
private:
|
||||
// Page by page decoders; each gets a bit ad hoc so
|
||||
// it is neater to separate them.
|
||||
Preinstruction decode0(uint16_t instruction);
|
||||
Preinstruction decode1(uint16_t instruction);
|
||||
Preinstruction decode2(uint16_t instruction);
|
||||
Preinstruction decode3(uint16_t instruction);
|
||||
Preinstruction decode4(uint16_t instruction);
|
||||
Preinstruction decode5(uint16_t instruction);
|
||||
Preinstruction decode6(uint16_t instruction);
|
||||
Preinstruction decode7(uint16_t instruction);
|
||||
Preinstruction decode8(uint16_t instruction);
|
||||
Preinstruction decode9(uint16_t instruction);
|
||||
Preinstruction decodeA(uint16_t instruction);
|
||||
Preinstruction decodeB(uint16_t instruction);
|
||||
Preinstruction decodeC(uint16_t instruction);
|
||||
Preinstruction decodeD(uint16_t instruction);
|
||||
Preinstruction decodeE(uint16_t instruction);
|
||||
Preinstruction decodeF(uint16_t instruction);
|
||||
|
||||
using OpT = uint8_t;
|
||||
|
||||
// Specific instruction decoders.
|
||||
template <OpT operation, bool validate = true> Preinstruction decode(uint16_t instruction);
|
||||
template <OpT operation, bool validate> Preinstruction validated(
|
||||
AddressingMode op1_mode = AddressingMode::None, int op1_reg = 0,
|
||||
AddressingMode op2_mode = AddressingMode::None, int op2_reg = 0
|
||||
);
|
||||
template <uint8_t op> 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
|
||||
// time that's knowable from the Operation alone, hence the rather awkward
|
||||
// extension of @c Operation.
|
||||
enum ExtendedOperation: OpT {
|
||||
MOVEMtoRl = uint8_t(Operation::Max) + 1, MOVEMtoRw,
|
||||
MOVEMtoMl, MOVEMtoMw,
|
||||
|
||||
MOVEPtoRl, MOVEPtoRw,
|
||||
MOVEPtoMl, MOVEPtoMw,
|
||||
|
||||
MOVEQ,
|
||||
|
||||
ADDQb, ADDQw, ADDQl,
|
||||
ADDQAw, ADDQAl,
|
||||
SUBQb, SUBQw, SUBQl,
|
||||
SUBQAw, SUBQAl,
|
||||
|
||||
ADDIb, ADDIw, ADDIl,
|
||||
ORIb, ORIw, ORIl,
|
||||
SUBIb, SUBIw, SUBIl,
|
||||
ANDIb, ANDIw, ANDIl,
|
||||
EORIb, EORIw, EORIl,
|
||||
CMPIb, CMPIw, CMPIl,
|
||||
|
||||
BTSTI, BCHGI, BCLRI, BSETI,
|
||||
|
||||
CMPMb, CMPMw, CMPMl,
|
||||
|
||||
MOVEq,
|
||||
|
||||
ADDtoMb, ADDtoMw, ADDtoMl,
|
||||
ADDtoRb, ADDtoRw, ADDtoRl,
|
||||
|
||||
SUBtoMb, SUBtoMw, SUBtoMl,
|
||||
SUBtoRb, SUBtoRw, SUBtoRl,
|
||||
|
||||
ANDtoMb, ANDtoMw, ANDtoMl,
|
||||
ANDtoRb, ANDtoRw, ANDtoRl,
|
||||
|
||||
ORtoMb, ORtoMw, ORtoMl,
|
||||
ORtoRb, ORtoRw, ORtoRl,
|
||||
|
||||
EXGRtoR, EXGAtoA, EXGRtoA,
|
||||
};
|
||||
|
||||
static constexpr Operation operation(OpT op);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* InstructionSets_M68k_Decoder_hpp */
|
392
InstructionSets/M68k/Instruction.hpp
Normal file
392
InstructionSets/M68k/Instruction.hpp
Normal file
@ -0,0 +1,392 @@
|
||||
//
|
||||
// Instruction.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 10/04/2022.
|
||||
// Copyright © 2022 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef InstructionSets_68k_Instruction_hpp
|
||||
#define InstructionSets_68k_Instruction_hpp
|
||||
|
||||
#include <cstdint>
|
||||
#include "Model.hpp"
|
||||
|
||||
namespace InstructionSet {
|
||||
namespace M68k {
|
||||
|
||||
enum class Operation: uint8_t {
|
||||
Undefined,
|
||||
|
||||
NOP,
|
||||
|
||||
ABCD, SBCD, NBCD,
|
||||
|
||||
ADDb, ADDw, ADDl,
|
||||
ADDAw, ADDAl,
|
||||
ADDXb, ADDXw, ADDXl,
|
||||
|
||||
SUBb, SUBw, SUBl,
|
||||
SUBAw, SUBAl,
|
||||
SUBXb, SUBXw, SUBXl,
|
||||
|
||||
MOVEb, MOVEw, MOVEl,
|
||||
MOVEAw, MOVEAl,
|
||||
LEA, PEA,
|
||||
|
||||
MOVEtoSR, MOVEfromSR,
|
||||
MOVEtoCCR,
|
||||
MOVEtoUSP, MOVEfromUSP,
|
||||
|
||||
ORItoSR, ORItoCCR,
|
||||
ANDItoSR, ANDItoCCR,
|
||||
EORItoSR, EORItoCCR,
|
||||
|
||||
BTST, BCLR,
|
||||
BCHG, BSET,
|
||||
|
||||
CMPb, CMPw, CMPl,
|
||||
CMPAw, CMPAl,
|
||||
TSTb, TSTw, TSTl,
|
||||
|
||||
JMP,
|
||||
JSR, RTS,
|
||||
DBcc,
|
||||
Scc,
|
||||
|
||||
Bccb, Bccw, Bccl,
|
||||
BSRb, BSRw, BSRl,
|
||||
|
||||
CLRb, CLRw, CLRl,
|
||||
NEGXb, NEGXw, NEGXl,
|
||||
NEGb, NEGw, NEGl,
|
||||
|
||||
ASLb, ASLw, ASLl, ASLm,
|
||||
ASRb, ASRw, ASRl, ASRm,
|
||||
LSLb, LSLw, LSLl, LSLm,
|
||||
LSRb, LSRw, LSRl, LSRm,
|
||||
ROLb, ROLw, ROLl, ROLm,
|
||||
RORb, RORw, RORl, RORm,
|
||||
ROXLb, ROXLw, ROXLl, ROXLm,
|
||||
ROXRb, ROXRw, ROXRl, ROXRm,
|
||||
|
||||
MOVEMl, MOVEMw,
|
||||
MOVEPl, MOVEPw,
|
||||
|
||||
ANDb, ANDw, ANDl,
|
||||
EORb, EORw, EORl,
|
||||
NOTb, NOTw, NOTl,
|
||||
ORb, ORw, ORl,
|
||||
|
||||
MULU, MULS,
|
||||
DIVU, DIVS,
|
||||
|
||||
RTE, RTR,
|
||||
|
||||
TRAP, TRAPV,
|
||||
CHK,
|
||||
|
||||
EXG, SWAP,
|
||||
|
||||
TAS,
|
||||
|
||||
EXTbtow, EXTwtol,
|
||||
|
||||
LINKw, UNLINK,
|
||||
|
||||
STOP, RESET,
|
||||
|
||||
Max = RESET
|
||||
};
|
||||
|
||||
template <Model model>
|
||||
constexpr bool requires_supervisor(Operation op) {
|
||||
switch(op) {
|
||||
case Operation::MOVEfromSR:
|
||||
if constexpr (model == Model::M68000) {
|
||||
return false;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case Operation::ORItoSR: case Operation::ANDItoSR:
|
||||
case Operation::EORItoSR: case Operation::RTE:
|
||||
case Operation::RESET: case Operation::STOP:
|
||||
case Operation::MOVEtoUSP: case Operation::MOVEfromUSP:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
enum class DataSize {
|
||||
Byte = 0,
|
||||
Word = 1,
|
||||
LongWord = 2,
|
||||
};
|
||||
|
||||
/// Classifies operations by the size of their memory accesses, if any.
|
||||
constexpr DataSize size(Operation operation) {
|
||||
switch(operation) {
|
||||
// These are given a value arbitrarily, to
|
||||
// complete the switch statement.
|
||||
case Operation::Undefined:
|
||||
case Operation::NOP:
|
||||
case Operation::STOP:
|
||||
case Operation::RESET:
|
||||
case Operation::RTE: case Operation::RTR:
|
||||
case Operation::TRAP:
|
||||
case Operation::TRAPV:
|
||||
|
||||
case Operation::ABCD: case Operation::SBCD:
|
||||
case Operation::NBCD:
|
||||
case Operation::ADDb: case Operation::ADDXb:
|
||||
case Operation::SUBb: case Operation::SUBXb:
|
||||
case Operation::MOVEb:
|
||||
case Operation::ORItoCCR:
|
||||
case Operation::ANDItoCCR:
|
||||
case Operation::EORItoCCR:
|
||||
case Operation::BTST: case Operation::BCLR:
|
||||
case Operation::BCHG: case Operation::BSET:
|
||||
case Operation::CMPb: case Operation::TSTb:
|
||||
case Operation::Bccb: case Operation::BSRb:
|
||||
case Operation::CLRb:
|
||||
case Operation::NEGXb: case Operation::NEGb:
|
||||
case Operation::ASLb: case Operation::ASRb:
|
||||
case Operation::LSLb: case Operation::LSRb:
|
||||
case Operation::ROLb: case Operation::RORb:
|
||||
case Operation::ROXLb: case Operation::ROXRb:
|
||||
case Operation::ANDb: case Operation::EORb:
|
||||
case Operation::NOTb: case Operation::ORb:
|
||||
case Operation::CHK:
|
||||
case Operation::TAS:
|
||||
return DataSize::Byte;
|
||||
|
||||
case Operation::ADDw: case Operation::ADDAw:
|
||||
case Operation::ADDXw: case Operation::SUBw:
|
||||
case Operation::SUBAw: case Operation::SUBXw:
|
||||
case Operation::MOVEw: case Operation::MOVEAw:
|
||||
case Operation::ORItoSR:
|
||||
case Operation::ANDItoSR:
|
||||
case Operation::EORItoSR:
|
||||
case Operation::MOVEtoSR:
|
||||
case Operation::MOVEfromSR:
|
||||
case Operation::MOVEtoCCR:
|
||||
case Operation::CMPw: case Operation::CMPAw:
|
||||
case Operation::TSTw:
|
||||
case Operation::DBcc: case Operation::Scc:
|
||||
case Operation::Bccw: case Operation::BSRw:
|
||||
case Operation::CLRw:
|
||||
case Operation::NEGXw: case Operation::NEGw:
|
||||
case Operation::ASLw: case Operation::ASLm:
|
||||
case Operation::ASRw: case Operation::ASRm:
|
||||
case Operation::LSLw: case Operation::LSLm:
|
||||
case Operation::LSRw: case Operation::LSRm:
|
||||
case Operation::ROLw: case Operation::ROLm:
|
||||
case Operation::RORw: case Operation::RORm:
|
||||
case Operation::ROXLw: case Operation::ROXLm:
|
||||
case Operation::ROXRw: case Operation::ROXRm:
|
||||
case Operation::MOVEMw:
|
||||
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::EXTbtow:
|
||||
case Operation::LINKw:
|
||||
return DataSize::Word;
|
||||
|
||||
case Operation::ADDl: case Operation::ADDAl:
|
||||
case Operation::ADDXl: case Operation::SUBl:
|
||||
case Operation::SUBAl: case Operation::SUBXl:
|
||||
case Operation::MOVEl: case Operation::MOVEAl:
|
||||
case Operation::LEA: case Operation::PEA:
|
||||
case Operation::EXG: case Operation::SWAP:
|
||||
case Operation::MOVEtoUSP:
|
||||
case Operation::MOVEfromUSP:
|
||||
case Operation::CMPl: case Operation::CMPAl:
|
||||
case Operation::TSTl:
|
||||
case Operation::JMP: case Operation::JSR:
|
||||
case Operation::RTS:
|
||||
case Operation::Bccl: case Operation::BSRl:
|
||||
case Operation::CLRl:
|
||||
case Operation::NEGXl: case Operation::NEGl:
|
||||
case Operation::ASLl: case Operation::ASRl:
|
||||
case Operation::LSLl: case Operation::LSRl:
|
||||
case Operation::ROLl: case Operation::RORl:
|
||||
case Operation::ROXLl: case Operation::ROXRl:
|
||||
case Operation::MOVEMl:
|
||||
case Operation::MOVEPl:
|
||||
case Operation::ANDl: case Operation::EORl:
|
||||
case Operation::NOTl: case Operation::ORl:
|
||||
case Operation::EXTwtol:
|
||||
case Operation::UNLINK:
|
||||
return DataSize::LongWord;
|
||||
}
|
||||
}
|
||||
|
||||
template <Operation op>
|
||||
constexpr uint32_t quick(uint16_t instruction) {
|
||||
switch(op) {
|
||||
case Operation::Bccb:
|
||||
case Operation::BSRb:
|
||||
case Operation::MOVEl: return uint32_t(int8_t(instruction));
|
||||
case Operation::TRAP: return uint32_t(instruction & 15);
|
||||
default: {
|
||||
uint32_t value = (instruction >> 9) & 7;
|
||||
value |= (value - 1)&8;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr uint32_t quick(Operation op, uint16_t instruction) {
|
||||
switch(op) {
|
||||
case Operation::MOVEl: return quick<Operation::MOVEl>(instruction);
|
||||
case Operation::Bccb: return quick<Operation::Bccb>(instruction);
|
||||
case Operation::BSRb: return quick<Operation::BSRb>(instruction);
|
||||
case Operation::TRAP: return quick<Operation::TRAP>(instruction);
|
||||
|
||||
default:
|
||||
// ADDw is arbitrary; anything other than those listed above will do.
|
||||
return quick<Operation::ADDw>(instruction);
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates the addressing mode applicable to an operand.
|
||||
///
|
||||
/// Implementation notes:
|
||||
///
|
||||
/// Those entries starting 0b00 or 0b01 are mapped as per the 68000's native encoding;
|
||||
/// those starting 0b00 are those which are indicated directly by a mode field and those starting
|
||||
/// 0b01 are those which are indicated by a register field given a mode of 0b111. The only minor
|
||||
/// exception is AddressRegisterDirect, which exists on a 68000 but isn't specifiable by a
|
||||
/// mode and register, it's contextual based on the instruction.
|
||||
///
|
||||
/// Those modes starting in 0b10 are the various extended addressing modes introduced as
|
||||
/// of the 68020, which can be detected only after interpreting an extension word. At the
|
||||
/// Preinstruction stage:
|
||||
///
|
||||
/// * AddressRegisterIndirectWithIndexBaseDisplacement, MemoryIndirectPostindexed
|
||||
/// and MemoryIndirectPreindexed will have been partially decoded as
|
||||
/// AddressRegisterIndirectWithIndex8bitDisplacement; and
|
||||
/// * ProgramCounterIndirectWithIndexBaseDisplacement,
|
||||
/// ProgramCounterMemoryIndirectPostindexed and
|
||||
/// ProgramCounterMemoryIndirectPreindexed will have been partially decoded
|
||||
/// as ProgramCounterIndirectWithIndex8bitDisplacement.
|
||||
enum class AddressingMode: uint8_t {
|
||||
/// No adddressing mode; this operand doesn't exist.
|
||||
None = 0b01'101,
|
||||
|
||||
/// Dn
|
||||
DataRegisterDirect = 0b00'000,
|
||||
|
||||
/// An
|
||||
AddressRegisterDirect = 0b00'001,
|
||||
/// (An)
|
||||
AddressRegisterIndirect = 0b00'010,
|
||||
/// (An)+
|
||||
AddressRegisterIndirectWithPostincrement = 0b00'011,
|
||||
/// -(An)
|
||||
AddressRegisterIndirectWithPredecrement = 0b00'100,
|
||||
/// (d16, An)
|
||||
AddressRegisterIndirectWithDisplacement = 0b00'101,
|
||||
/// (d8, An, Xn)
|
||||
AddressRegisterIndirectWithIndex8bitDisplacement = 0b00'110,
|
||||
/// (bd, An, Xn)
|
||||
AddressRegisterIndirectWithIndexBaseDisplacement = 0b10'000,
|
||||
|
||||
/// ([bd, An, Xn], od)
|
||||
MemoryIndirectPostindexed = 0b10'001,
|
||||
/// ([bd, An], Xn, od)
|
||||
MemoryIndirectPreindexed = 0b10'010,
|
||||
|
||||
/// (d16, PC)
|
||||
ProgramCounterIndirectWithDisplacement = 0b01'010,
|
||||
/// (d8, PC, Xn)
|
||||
ProgramCounterIndirectWithIndex8bitDisplacement = 0b01'011,
|
||||
/// (bd, PC, Xn)
|
||||
ProgramCounterIndirectWithIndexBaseDisplacement = 0b10'011,
|
||||
/// ([bd, PC, Xn], od)
|
||||
ProgramCounterMemoryIndirectPostindexed = 0b10'100,
|
||||
/// ([bc, PC], Xn, od)
|
||||
ProgramCounterMemoryIndirectPreindexed = 0b10'101,
|
||||
|
||||
/// (xxx).W
|
||||
AbsoluteShort = 0b01'000,
|
||||
/// (xxx).L
|
||||
AbsoluteLong = 0b01'001,
|
||||
|
||||
/// #
|
||||
ImmediateData = 0b01'100,
|
||||
|
||||
/// .q; value is embedded in the opcode.
|
||||
Quick = 0b01'110,
|
||||
};
|
||||
|
||||
/*!
|
||||
A preinstruction is as much of an instruction as can be decoded with
|
||||
only the first instruction word — i.e. an operation, and:
|
||||
|
||||
* on the 68000 and 68010, the complete addressing modes;
|
||||
* on subsequent, a decent proportion of the addressing mode. See
|
||||
the notes on @c AddressingMode for potential aliasing.
|
||||
*/
|
||||
class Preinstruction {
|
||||
public:
|
||||
Operation operation = Operation::Undefined;
|
||||
|
||||
// Instructions come with 0, 1 or 2 operands;
|
||||
// the getters below act to provide a list of operands
|
||||
// that is terminated by an AddressingMode::None.
|
||||
//
|
||||
// For two-operand instructions, argument 0 is a source
|
||||
// and argument 1 is a destination.
|
||||
//
|
||||
// For one-operand instructions, only argument 0 will
|
||||
// be provided, and will be a source and/or destination as
|
||||
// per the semantics of the operation.
|
||||
|
||||
template <int index> AddressingMode mode() const {
|
||||
if constexpr (index > 1) {
|
||||
return AddressingMode::None;
|
||||
}
|
||||
return AddressingMode(operands_[index] & 0x1f);
|
||||
}
|
||||
template <int index> int reg() const {
|
||||
if constexpr (index > 1) {
|
||||
return 0;
|
||||
}
|
||||
return operands_[index] >> 5;
|
||||
}
|
||||
|
||||
bool requires_supervisor() {
|
||||
return flags_ & 0x80;
|
||||
}
|
||||
DataSize size() {
|
||||
return DataSize(flags_ & 0x7f);
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t operands_[2] = { uint8_t(AddressingMode::None), uint8_t(AddressingMode::None)};
|
||||
uint8_t flags_ = 0;
|
||||
|
||||
public:
|
||||
Preinstruction(
|
||||
Operation operation,
|
||||
AddressingMode op1_mode, int op1_reg,
|
||||
AddressingMode op2_mode, int op2_reg,
|
||||
bool is_supervisor,
|
||||
DataSize size) : operation(operation)
|
||||
{
|
||||
operands_[0] = uint8_t(op1_mode) | uint8_t(op1_reg << 5);
|
||||
operands_[1] = uint8_t(op2_mode) | uint8_t(op2_reg << 5);
|
||||
flags_ = (is_supervisor ? 0x80 : 0x00) | uint8_t(size);
|
||||
}
|
||||
|
||||
Preinstruction() {}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* InstructionSets_68k_Instruction_hpp */
|
26
InstructionSets/M68k/Model.hpp
Normal file
26
InstructionSets/M68k/Model.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
//
|
||||
// Model.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 15/04/2022.
|
||||
// Copyright © 2022 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef InstructionSets_M68k_Model_hpp
|
||||
#define InstructionSets_M68k_Model_hpp
|
||||
|
||||
namespace InstructionSet {
|
||||
namespace M68k {
|
||||
|
||||
enum class Model {
|
||||
M68000,
|
||||
M68010,
|
||||
M68020,
|
||||
M68030,
|
||||
M68040,
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* InstructionSets_M68k_Model_hpp */
|
@ -309,6 +309,8 @@
|
||||
4B74CF822312FA9C00500CE8 /* HFV.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B74CF802312FA9C00500CE8 /* HFV.cpp */; };
|
||||
4B74CF85231370BC00500CE8 /* MacintoshVolume.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B74CF83231370BC00500CE8 /* MacintoshVolume.cpp */; };
|
||||
4B74CF86231370BC00500CE8 /* MacintoshVolume.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B74CF83231370BC00500CE8 /* MacintoshVolume.cpp */; };
|
||||
4B75F979280D7C5100121055 /* 68000DecoderTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B75F978280D7C5100121055 /* 68000DecoderTests.mm */; };
|
||||
4B75F97B280D7C7700121055 /* 68000 Decoding in Resources */ = {isa = PBXBuildFile; fileRef = 4B75F97A280D7C7700121055 /* 68000 Decoding */; };
|
||||
4B778EEF23A5D6680000D260 /* AsyncTaskQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3940E51DA83C8300427841 /* AsyncTaskQueue.cpp */; };
|
||||
4B778EF023A5D68C0000D260 /* 68000Storage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFF1D3822337B0300838EA1 /* 68000Storage.cpp */; };
|
||||
4B778EF123A5D6B50000D260 /* 9918.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0E04F91FC9FA3100F43484 /* 9918.cpp */; };
|
||||
@ -422,6 +424,9 @@
|
||||
4B778F6223A5F35F0000D260 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B894500201967B4007DE474 /* File.cpp */; };
|
||||
4B778F6323A5F3630000D260 /* Tape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B894501201967B4007DE474 /* Tape.cpp */; };
|
||||
4B7913CC1DFCD80E00175A82 /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7913CA1DFCD80E00175A82 /* Video.cpp */; };
|
||||
4B7962A02819681F008130F9 /* Decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B79629F2819681F008130F9 /* Decoder.cpp */; };
|
||||
4B7962A12819681F008130F9 /* Decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B79629F2819681F008130F9 /* Decoder.cpp */; };
|
||||
4B7962A22819681F008130F9 /* Decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B79629F2819681F008130F9 /* Decoder.cpp */; };
|
||||
4B79A5011FC913C900EEDAD5 /* MSX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B79A4FF1FC913C900EEDAD5 /* MSX.cpp */; };
|
||||
4B79E4441E3AF38600141F11 /* cassette.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B79E4411E3AF38600141F11 /* cassette.png */; };
|
||||
4B79E4451E3AF38600141F11 /* floppy35.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B79E4421E3AF38600141F11 /* floppy35.png */; };
|
||||
@ -1411,10 +1416,16 @@
|
||||
4B74CF802312FA9C00500CE8 /* HFV.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HFV.cpp; sourceTree = "<group>"; };
|
||||
4B74CF83231370BC00500CE8 /* MacintoshVolume.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MacintoshVolume.cpp; path = Encodings/MacintoshVolume.cpp; sourceTree = "<group>"; };
|
||||
4B74CF84231370BC00500CE8 /* MacintoshVolume.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = MacintoshVolume.hpp; path = Encodings/MacintoshVolume.hpp; sourceTree = "<group>"; };
|
||||
4B75F978280D7C5100121055 /* 68000DecoderTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = 68000DecoderTests.mm; sourceTree = "<group>"; };
|
||||
4B75F97A280D7C7700121055 /* 68000 Decoding */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "68000 Decoding"; sourceTree = "<group>"; };
|
||||
4B77069C1EC904570053B588 /* Z80.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Z80.hpp; sourceTree = "<group>"; };
|
||||
4B770A961FE9EE770026DC70 /* CompoundSource.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CompoundSource.hpp; sourceTree = "<group>"; };
|
||||
4B7913CA1DFCD80E00175A82 /* Video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Video.cpp; sourceTree = "<group>"; };
|
||||
4B7913CB1DFCD80E00175A82 /* Video.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Video.hpp; sourceTree = "<group>"; };
|
||||
4B79629C2819681F008130F9 /* Instruction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Instruction.hpp; sourceTree = "<group>"; };
|
||||
4B79629D2819681F008130F9 /* Model.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Model.hpp; sourceTree = "<group>"; };
|
||||
4B79629E2819681F008130F9 /* Decoder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Decoder.hpp; sourceTree = "<group>"; };
|
||||
4B79629F2819681F008130F9 /* Decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Decoder.cpp; sourceTree = "<group>"; };
|
||||
4B79A4FE1FC9082300EEDAD5 /* TypedDynamicMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TypedDynamicMachine.hpp; sourceTree = "<group>"; };
|
||||
4B79A4FF1FC913C900EEDAD5 /* MSX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MSX.cpp; sourceTree = "<group>"; };
|
||||
4B79A5001FC913C900EEDAD5 /* MSX.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MSX.hpp; sourceTree = "<group>"; };
|
||||
@ -2392,22 +2403,23 @@
|
||||
4B1414631B588A1100E04248 /* Test Binaries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B018B88211930DE002A3937 /* 65C02_extended_opcodes_test.bin */,
|
||||
4BE211DD253E4E4800435408 /* 65C02_no_Rockwell_test.bin */,
|
||||
4B44EBF61DC9883B00A7820C /* 6502_functional_test.bin */,
|
||||
4B680CE323A555CA00451D43 /* 68000 Comparative Tests */,
|
||||
4B44EBF41DC987AE00A7820C /* AllSuiteA.bin */,
|
||||
4B75F97A280D7C7700121055 /* 68000 Decoding */,
|
||||
4B683B002727BE6F0043E541 /* Amiga Blitter Tests */,
|
||||
4B9252CD1E74D28200B76AF1 /* Atari ROMs */,
|
||||
4B44EBF81DC9898E00A7820C /* BCDTEST_beeb */,
|
||||
4BB0CAB127E51D2A00672A88 /* dingusdev PowerPC tests */,
|
||||
4B98A1CD1FFADEC400ADF63B /* MSX ROMs */,
|
||||
4B018B88211930DE002A3937 /* 65C02_extended_opcodes_test.bin */,
|
||||
4BE211DD253E4E4800435408 /* 65C02_no_Rockwell_test.bin */,
|
||||
4B44EBF61DC9883B00A7820C /* 6502_functional_test.bin */,
|
||||
4B44EBF41DC987AE00A7820C /* AllSuiteA.bin */,
|
||||
4B9F11CB22729B3500701480 /* OPCLOGR2.BIN */,
|
||||
4B8DF5212550D91400F3433C /* emudev.de krom traces */,
|
||||
4B2530F2244E6773007980BF /* FM Synthesis */,
|
||||
4BBF49B41ED2881600AB3669 /* FUSE */,
|
||||
4B4F475B2533EA64004245B8 /* jeek816 */,
|
||||
4B8DF5392550D91400F3433C /* krom 65816 */,
|
||||
4B98A1CD1FFADEC400ADF63B /* MSX ROMs */,
|
||||
4B9F11CB22729B3500701480 /* OPCLOGR2.BIN */,
|
||||
4B670A822401CB8400D4E002 /* Patrik Rak Z80 Tests */,
|
||||
4B9F11C72272375400701480 /* QL Startup */,
|
||||
4B85322B227793CA00F26553 /* TOS Startup */,
|
||||
@ -3142,6 +3154,17 @@
|
||||
path = Z80;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B79629B2819681F008130F9 /* M68k */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B79629C2819681F008130F9 /* Instruction.hpp */,
|
||||
4B79629D2819681F008130F9 /* Model.hpp */,
|
||||
4B79629E2819681F008130F9 /* Decoder.hpp */,
|
||||
4B79629F2819681F008130F9 /* Decoder.cpp */,
|
||||
);
|
||||
path = M68k;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B79A4FC1FC8FF9800EEDAD5 /* MSX */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -4133,6 +4156,7 @@
|
||||
4B90467322C6FADD000E2074 /* 68000BitwiseTests.mm */,
|
||||
4B680CE123A5553100451D43 /* 68000ComparativeTests.mm */,
|
||||
4B9D0C4C22C7DA1A00DE1AD3 /* 68000ControlFlowTests.mm */,
|
||||
4B75F978280D7C5100121055 /* 68000DecoderTests.mm */,
|
||||
4BC5C3DF22C994CC00795658 /* 68000MoveTests.mm */,
|
||||
4B9D0C4E22C7E0CF00DE1AD3 /* 68000RollShiftTests.mm */,
|
||||
4BD388872239E198002D14B5 /* 68000Tests.mm */,
|
||||
@ -4718,6 +4742,7 @@
|
||||
4BEDA45425B5ECAB000C2DBD /* CachingExecutor.hpp */,
|
||||
4BE8EB5425C0E9D40040BC40 /* Disassembler.hpp */,
|
||||
4BEDA3B625B25563000C2DBD /* README.md */,
|
||||
4B79629B2819681F008130F9 /* M68k */,
|
||||
4BEDA40925B2844B000C2DBD /* M50740 */,
|
||||
4BEDA3B325B25563000C2DBD /* PowerPC */,
|
||||
4BEDA3B725B25563000C2DBD /* x86 */,
|
||||
@ -5195,6 +5220,7 @@
|
||||
4BB2996E1B587D8400A49093 /* laxa in Resources */,
|
||||
4BB2990A1B587D8400A49093 /* aslzx in Resources */,
|
||||
4BB299281B587D8400A49093 /* cia2pb6 in Resources */,
|
||||
4B75F97B280D7C7700121055 /* 68000 Decoding in Resources */,
|
||||
4BB2991E1B587D8400A49093 /* branchwrap in Resources */,
|
||||
4BB299121B587D8400A49093 /* axsa in Resources */,
|
||||
4BB299561B587D8400A49093 /* eorz in Resources */,
|
||||
@ -5431,6 +5457,7 @@
|
||||
4BFEA2F02682A7B900EBF94C /* Dave.cpp in Sources */,
|
||||
4BDACBED22FFA5D20045EF7E /* ncr5380.cpp in Sources */,
|
||||
4BC131772346DE9100E4FF3D /* StaticAnalyser.cpp in Sources */,
|
||||
4B7962A22819681F008130F9 /* Decoder.cpp in Sources */,
|
||||
4B055ACF1FAE9B030060FFFF /* SoundGenerator.cpp in Sources */,
|
||||
4B4DEC08252BFA56004583AC /* 65816Base.cpp in Sources */,
|
||||
4B894519201967B4007DE474 /* ConfidenceCounter.cpp in Sources */,
|
||||
@ -5684,6 +5711,7 @@
|
||||
4B2B3A4C1F9B8FA70062DABF /* MemoryFuzzer.cpp in Sources */,
|
||||
4B9EC0EA26B384080060A31F /* Keyboard.cpp in Sources */,
|
||||
4B7913CC1DFCD80E00175A82 /* Video.cpp in Sources */,
|
||||
4B7962A02819681F008130F9 /* Decoder.cpp in Sources */,
|
||||
4BC57CD92436A62900FBC404 /* State.cpp in Sources */,
|
||||
4BDA00E622E699B000AC3CD0 /* CSMachine.mm in Sources */,
|
||||
4B4518831F75E91A00926311 /* PCMTrack.cpp in Sources */,
|
||||
@ -5862,6 +5890,7 @@
|
||||
4B778F3723A5F11C0000D260 /* Parser.cpp in Sources */,
|
||||
4B778F4523A5F1CD0000D260 /* SegmentParser.cpp in Sources */,
|
||||
4B90467422C6FADD000E2074 /* 68000BitwiseTests.mm in Sources */,
|
||||
4B7962A12819681F008130F9 /* Decoder.cpp in Sources */,
|
||||
4B778F2A23A5EF0F0000D260 /* BitReverse.cpp in Sources */,
|
||||
4B778F1D23A5ED470000D260 /* DiskController.cpp in Sources */,
|
||||
4B778F0023A5EB990000D260 /* G64.cpp in Sources */,
|
||||
@ -5891,6 +5920,7 @@
|
||||
4B778EFC23A5EB8B0000D260 /* AcornADF.cpp in Sources */,
|
||||
4B778F2023A5EDCE0000D260 /* HFV.cpp in Sources */,
|
||||
4B778F3323A5F0FB0000D260 /* MassStorageDevice.cpp in Sources */,
|
||||
4B75F979280D7C5100121055 /* 68000DecoderTests.mm in Sources */,
|
||||
4B778F2C23A5EF0F0000D260 /* ZX8081.cpp in Sources */,
|
||||
4B778F3023A5F0C50000D260 /* Macintosh.cpp in Sources */,
|
||||
4B3BA0D11D318B44005DD7A7 /* TestMachine6502.mm in Sources */,
|
||||
|
65538
OSBindings/Mac/Clock SignalTests/68000 Decoding/68000ops.json
Normal file
65538
OSBindings/Mac/Clock SignalTests/68000 Decoding/68000ops.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,5 @@
|
||||
# 68000 Opcode list
|
||||
|
||||
This is **work in progress** and acts primarily as a *regression test*.
|
||||
|
||||
The objective is to get it to perfect, but it is unlikely currently to be there.
|
290
OSBindings/Mac/Clock SignalTests/68000DecoderTests.mm
Normal file
290
OSBindings/Mac/Clock SignalTests/68000DecoderTests.mm
Normal file
@ -0,0 +1,290 @@
|
||||
//
|
||||
// m68kDecoderTests.m
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 18/04/2022.
|
||||
// Copyright 2022 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#include "../../../InstructionSets/M68k/Decoder.hpp"
|
||||
|
||||
using namespace InstructionSet::M68k;
|
||||
|
||||
@interface M68000DecoderTests : XCTestCase
|
||||
@end
|
||||
|
||||
namespace {
|
||||
|
||||
template <int index> NSString *operand(Preinstruction instruction, uint16_t opcode) {
|
||||
switch(instruction.mode<index>()) {
|
||||
default: return [NSString stringWithFormat:@"[Mode %d?]", int(instruction.mode<index>())];
|
||||
|
||||
case AddressingMode::None:
|
||||
return @"";
|
||||
|
||||
case AddressingMode::DataRegisterDirect:
|
||||
return [NSString stringWithFormat:@"D%d", instruction.reg<index>()];
|
||||
|
||||
case AddressingMode::AddressRegisterDirect:
|
||||
return [NSString stringWithFormat:@"A%d", instruction.reg<index>()];
|
||||
case AddressingMode::AddressRegisterIndirect:
|
||||
return [NSString stringWithFormat:@"(A%d)", instruction.reg<index>()];
|
||||
case AddressingMode::AddressRegisterIndirectWithPostincrement:
|
||||
return [NSString stringWithFormat:@"(A%d)+", instruction.reg<index>()];
|
||||
case AddressingMode::AddressRegisterIndirectWithPredecrement:
|
||||
return [NSString stringWithFormat:@"-(A%d)", instruction.reg<index>()];
|
||||
case AddressingMode::AddressRegisterIndirectWithDisplacement:
|
||||
return [NSString stringWithFormat:@"(d16, A%d)", instruction.reg<index>()];
|
||||
case AddressingMode::AddressRegisterIndirectWithIndex8bitDisplacement:
|
||||
return [NSString stringWithFormat:@"(d8, A%d, Xn)", instruction.reg<index>()];
|
||||
|
||||
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::ImmediateData:
|
||||
return @"#";
|
||||
|
||||
case AddressingMode::Quick:
|
||||
return [NSString stringWithFormat:@"%d", quick(instruction.operation, opcode)];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@implementation M68000DecoderTests
|
||||
|
||||
- (void)testInstructionSpecs {
|
||||
NSData *const testData =
|
||||
[NSData dataWithContentsOfURL:
|
||||
[[NSBundle bundleForClass:[self class]]
|
||||
URLForResource:@"68000ops"
|
||||
withExtension:@"json"
|
||||
subdirectory:@"68000 Decoding"]];
|
||||
|
||||
NSDictionary<NSString *, NSString *> *const decodings = [NSJSONSerialization JSONObjectWithData:testData options:0 error:nil];
|
||||
XCTAssertNotNil(decodings);
|
||||
|
||||
Predecoder<Model::M68000> decoder;
|
||||
for(int instr = 0; instr < 65536; instr++) {
|
||||
NSString *const instrName = [NSString stringWithFormat:@"%04x", instr];
|
||||
NSString *const expected = decodings[instrName];
|
||||
XCTAssertNotNil(expected);
|
||||
|
||||
const auto found = decoder.decode(uint16_t(instr));
|
||||
|
||||
NSString *instruction;
|
||||
switch(found.operation) {
|
||||
case Operation::Undefined: instruction = @"None"; break;
|
||||
case Operation::NOP: instruction = @"NOP"; break;
|
||||
case Operation::ABCD: instruction = @"ABCD"; break;
|
||||
case Operation::SBCD: instruction = @"SBCD"; break;
|
||||
case Operation::NBCD: instruction = @"NBCD"; break;
|
||||
|
||||
case Operation::ADDb: instruction = @"ADD.b"; break;
|
||||
case Operation::ADDw: instruction = @"ADD.w"; break;
|
||||
case Operation::ADDl: instruction = @"ADD.l"; break;
|
||||
|
||||
case Operation::ADDAw: instruction = @"ADDA.w"; break;
|
||||
case Operation::ADDAl: instruction = @"ADDA.l"; break;
|
||||
|
||||
case Operation::ADDXb: instruction = @"ADDX.b"; break;
|
||||
case Operation::ADDXw: instruction = @"ADDX.w"; break;
|
||||
case Operation::ADDXl: instruction = @"ADDX.l"; break;
|
||||
|
||||
case Operation::SUBb: instruction = @"SUB.b"; break;
|
||||
case Operation::SUBw: instruction = @"SUB.w"; break;
|
||||
case Operation::SUBl: instruction = @"SUB.l"; break;
|
||||
|
||||
case Operation::SUBAw: instruction = @"SUBA.w"; break;
|
||||
case Operation::SUBAl: instruction = @"SUBA.l"; break;
|
||||
|
||||
case Operation::SUBXb: instruction = @"SUBX.b"; break;
|
||||
case Operation::SUBXw: instruction = @"SUBX.w"; break;
|
||||
case Operation::SUBXl: instruction = @"SUBX.l"; break;
|
||||
|
||||
case Operation::MOVEb: instruction = @"MOVE.b"; break;
|
||||
case Operation::MOVEw: instruction = @"MOVE.w"; break;
|
||||
case Operation::MOVEl:
|
||||
if(found.mode<0>() == AddressingMode::Quick) {
|
||||
instruction = @"MOVE.q";
|
||||
} else {
|
||||
instruction = @"MOVE.l";
|
||||
}
|
||||
break;
|
||||
|
||||
case Operation::MOVEAw: instruction = @"MOVEA.w"; break;
|
||||
case Operation::MOVEAl: instruction = @"MOVEA.l"; break;
|
||||
|
||||
case Operation::LEA: instruction = @"LEA"; break;
|
||||
case Operation::PEA: instruction = @"PEA"; break;
|
||||
|
||||
case Operation::MOVEtoSR: instruction = @"MOVEtoSR"; break;
|
||||
case Operation::MOVEfromSR: instruction = @"MOVEfromSR"; break;
|
||||
case Operation::MOVEtoCCR: instruction = @"MOVEtoCCR"; break;
|
||||
case Operation::MOVEtoUSP: instruction = @"MOVEtoUSP"; break;
|
||||
case Operation::MOVEfromUSP: instruction = @"MOVEfromUSP"; break;
|
||||
|
||||
case Operation::ORItoSR: instruction = @"ORItoSR"; break;
|
||||
case Operation::ORItoCCR: instruction = @"ORItoCCR"; break;
|
||||
case Operation::ANDItoSR: instruction = @"ANDItoSR"; break;
|
||||
case Operation::ANDItoCCR: instruction = @"ANDItoCCR"; break;
|
||||
case Operation::EORItoSR: instruction = @"EORItoSR"; break;
|
||||
case Operation::EORItoCCR: instruction = @"EORItoCCR"; break;
|
||||
|
||||
case Operation::BTST: instruction = @"BTST"; break;
|
||||
case Operation::BCLR: instruction = @"BCLR"; break;
|
||||
case Operation::BCHG: instruction = @"BCHG"; break;
|
||||
case Operation::BSET: instruction = @"BSET"; break;
|
||||
|
||||
case Operation::CMPb: instruction = @"CMP.b"; break;
|
||||
case Operation::CMPw: instruction = @"CMP.w"; break;
|
||||
case Operation::CMPl: instruction = @"CMP.l"; break;
|
||||
|
||||
case Operation::CMPAw: instruction = @"CMPA.w"; break;
|
||||
case Operation::CMPAl: instruction = @"CMPA.l"; break;
|
||||
|
||||
case Operation::TSTb: instruction = @"TST.b"; break;
|
||||
case Operation::TSTw: instruction = @"TST.w"; break;
|
||||
case Operation::TSTl: instruction = @"TST.l"; break;
|
||||
|
||||
case Operation::JMP: instruction = @"JMP"; break;
|
||||
case Operation::JSR: instruction = @"JSR"; break;
|
||||
case Operation::RTS: instruction = @"RTS"; break;
|
||||
case Operation::DBcc: instruction = @"DBcc"; break;
|
||||
case Operation::Scc: instruction = @"Scc"; break;
|
||||
|
||||
case Operation::Bccb:
|
||||
case Operation::Bccl:
|
||||
case Operation::Bccw: instruction = @"Bcc"; break;
|
||||
|
||||
case Operation::BSRb:
|
||||
case Operation::BSRl:
|
||||
case Operation::BSRw: instruction = @"BSR"; break;
|
||||
|
||||
case Operation::CLRb: instruction = @"CLR.b"; break;
|
||||
case Operation::CLRw: instruction = @"CLR.w"; break;
|
||||
case Operation::CLRl: instruction = @"CLR.l"; break;
|
||||
|
||||
case Operation::NEGXb: instruction = @"NEGX.b"; break;
|
||||
case Operation::NEGXw: instruction = @"NEGX.w"; break;
|
||||
case Operation::NEGXl: instruction = @"NEGX.l"; break;
|
||||
|
||||
case Operation::NEGb: instruction = @"NEG.b"; break;
|
||||
case Operation::NEGw: instruction = @"NEG.w"; break;
|
||||
case Operation::NEGl: instruction = @"NEG.l"; break;
|
||||
|
||||
case Operation::ASLb: instruction = @"ASL.b"; break;
|
||||
case Operation::ASLw: instruction = @"ASL.w"; break;
|
||||
case Operation::ASLl: instruction = @"ASL.l"; break;
|
||||
case Operation::ASLm: instruction = @"ASL.w"; break;
|
||||
|
||||
case Operation::ASRb: instruction = @"ASR.b"; break;
|
||||
case Operation::ASRw: instruction = @"ASR.w"; break;
|
||||
case Operation::ASRl: instruction = @"ASR.l"; break;
|
||||
case Operation::ASRm: instruction = @"ASR.w"; break;
|
||||
|
||||
case Operation::LSLb: instruction = @"LSL.b"; break;
|
||||
case Operation::LSLw: instruction = @"LSL.w"; break;
|
||||
case Operation::LSLl: instruction = @"LSL.l"; break;
|
||||
case Operation::LSLm: instruction = @"LSL.w"; break;
|
||||
|
||||
case Operation::LSRb: instruction = @"LSR.b"; break;
|
||||
case Operation::LSRw: instruction = @"LSR.w"; break;
|
||||
case Operation::LSRl: instruction = @"LSR.l"; break;
|
||||
case Operation::LSRm: instruction = @"LSR.w"; break;
|
||||
|
||||
case Operation::ROLb: instruction = @"ROL.b"; break;
|
||||
case Operation::ROLw: instruction = @"ROL.w"; break;
|
||||
case Operation::ROLl: instruction = @"ROL.l"; break;
|
||||
case Operation::ROLm: instruction = @"ROL.w"; break;
|
||||
|
||||
case Operation::RORb: instruction = @"ROR.b"; break;
|
||||
case Operation::RORw: instruction = @"ROR.w"; break;
|
||||
case Operation::RORl: instruction = @"ROR.l"; break;
|
||||
case Operation::RORm: instruction = @"ROR.w"; break;
|
||||
|
||||
case Operation::ROXLb: instruction = @"ROXL.b"; break;
|
||||
case Operation::ROXLw: instruction = @"ROXL.w"; break;
|
||||
case Operation::ROXLl: instruction = @"ROXL.l"; break;
|
||||
case Operation::ROXLm: instruction = @"ROXL.w"; break;
|
||||
|
||||
case Operation::ROXRb: instruction = @"ROXR.b"; break;
|
||||
case Operation::ROXRw: instruction = @"ROXR.w"; break;
|
||||
case Operation::ROXRl: instruction = @"ROXR.l"; break;
|
||||
case Operation::ROXRm: instruction = @"ROXR.w"; break;
|
||||
|
||||
case Operation::MOVEMl: instruction = @"MOVEM.l"; break;
|
||||
case Operation::MOVEMw: instruction = @"MOVEM.w"; break;
|
||||
|
||||
case Operation::MOVEPl: instruction = @"MOVEP.l"; break;
|
||||
case Operation::MOVEPw: instruction = @"MOVEP.w"; break;
|
||||
|
||||
case Operation::ANDb: instruction = @"AND.b"; break;
|
||||
case Operation::ANDw: instruction = @"AND.w"; break;
|
||||
case Operation::ANDl: instruction = @"AND.l"; break;
|
||||
|
||||
case Operation::EORb: instruction = @"EOR.b"; break;
|
||||
case Operation::EORw: instruction = @"EOR.w"; break;
|
||||
case Operation::EORl: instruction = @"EOR.l"; break;
|
||||
|
||||
case Operation::NOTb: instruction = @"NOT.b"; break;
|
||||
case Operation::NOTw: instruction = @"NOT.w"; break;
|
||||
case Operation::NOTl: instruction = @"NOT.l"; break;
|
||||
|
||||
case Operation::ORb: instruction = @"OR.b"; break;
|
||||
case Operation::ORw: instruction = @"OR.w"; break;
|
||||
case Operation::ORl: instruction = @"OR.l"; break;
|
||||
|
||||
case Operation::MULU: instruction = @"MULU"; break;
|
||||
case Operation::MULS: instruction = @"MULS"; break;
|
||||
case Operation::DIVU: instruction = @"DIVU"; break;
|
||||
case Operation::DIVS: instruction = @"DIVS"; break;
|
||||
|
||||
case Operation::RTE: instruction = @"RTE"; break;
|
||||
case Operation::RTR: instruction = @"RTR"; break;
|
||||
|
||||
case Operation::TRAP: instruction = @"TRAP"; break;
|
||||
case Operation::TRAPV: instruction = @"TRAPV"; break;
|
||||
case Operation::CHK: instruction = @"CHK"; break;
|
||||
|
||||
case Operation::EXG: instruction = @"EXG"; break;
|
||||
case Operation::SWAP: instruction = @"SWAP"; break;
|
||||
|
||||
case Operation::TAS: instruction = @"TAS"; break;
|
||||
|
||||
case Operation::EXTbtow: instruction = @"EXT.w"; break;
|
||||
case Operation::EXTwtol: instruction = @"EXT.l"; break;
|
||||
|
||||
case Operation::LINKw: instruction = @"LINK"; break;
|
||||
case Operation::UNLINK: instruction = @"UNLINK"; break;
|
||||
|
||||
case Operation::STOP: instruction = @"STOP"; break;
|
||||
case Operation::RESET: instruction = @"RESET"; break;
|
||||
|
||||
// For now, skip any unmapped operations.
|
||||
default:
|
||||
XCTAssert(false, @"Operation %d unhandled by test case", int(found.operation));
|
||||
continue;
|
||||
}
|
||||
|
||||
NSString *const operand1 = operand<0>(found, uint16_t(instr));
|
||||
NSString *const operand2 = operand<1>(found, uint16_t(instr));
|
||||
|
||||
if(operand1.length) instruction = [instruction stringByAppendingFormat:@" %@", operand1];
|
||||
if(operand2.length) instruction = [instruction stringByAppendingFormat:@", %@", operand2];
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
@ -78,6 +78,7 @@ SOURCES += \
|
||||
$$SRC/Inputs/*.cpp \
|
||||
\
|
||||
$$SRC/InstructionSets/M50740/*.cpp \
|
||||
$$SRC/InstructionSets/M68k/*.cpp \
|
||||
$$SRC/InstructionSets/PowerPC/*.cpp \
|
||||
$$SRC/InstructionSets/x86/*.cpp \
|
||||
\
|
||||
@ -211,6 +212,7 @@ HEADERS += \
|
||||
$$SRC/Inputs/QuadratureMouse/*.hpp \
|
||||
\
|
||||
$$SRC/InstructionSets/M50740/*.hpp \
|
||||
$$SRC/InstructionSets/M68k/*.hpp \
|
||||
$$SRC/InstructionSets/PowerPC/*.hpp \
|
||||
$$SRC/InstructionSets/x86/*.hpp \
|
||||
\
|
||||
|
@ -65,6 +65,7 @@ SOURCES += glob.glob('../../Configurable/*.cpp')
|
||||
SOURCES += glob.glob('../../Inputs/*.cpp')
|
||||
|
||||
SOURCES += glob.glob('../../InstructionSets/M50740/*.cpp')
|
||||
SOURCES += glob.glob('../../InstructionSets/M68k/*.cpp')
|
||||
SOURCES += glob.glob('../../InstructionSets/PowerPC/*.cpp')
|
||||
SOURCES += glob.glob('../../InstructionSets/x86/*.cpp')
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user