2022-04-11 19:00:55 +00:00
|
|
|
|
//
|
|
|
|
|
// Decoder.cpp
|
|
|
|
|
// Clock Signal
|
|
|
|
|
//
|
|
|
|
|
// Created by Thomas Harte on 10/04/2022.
|
|
|
|
|
// Copyright © 2022 Thomas Harte. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#include "Decoder.hpp"
|
|
|
|
|
|
2022-04-12 11:49:08 +00:00
|
|
|
|
#include <cassert>
|
|
|
|
|
|
2022-04-11 19:00:55 +00:00
|
|
|
|
using namespace InstructionSet::M68k;
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
2022-04-22 19:11:41 +00:00
|
|
|
|
constexpr AddressingMode extended_modes[] = {
|
|
|
|
|
AddressingMode::AbsoluteShort, // 1'000
|
|
|
|
|
AddressingMode::AbsoluteLong, // 1'001
|
|
|
|
|
AddressingMode::ProgramCounterIndirectWithDisplacement, // 1'010
|
|
|
|
|
AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement, // 1'011
|
|
|
|
|
AddressingMode::ImmediateData, // 1'100
|
|
|
|
|
AddressingMode::None, // [1'101]
|
|
|
|
|
AddressingMode::None, // [1'110]
|
|
|
|
|
AddressingMode::None, // [1'111]
|
|
|
|
|
};
|
|
|
|
|
|
2022-04-11 19:00:55 +00:00
|
|
|
|
/// @returns The @c AddressingMode given the specified mode and reg, subject to potential
|
2023-05-12 18:14:45 +00:00
|
|
|
|
/// aliasing on the '020+ as described above the @c AddressingMode enum.
|
2024-10-14 01:34:01 +00:00
|
|
|
|
constexpr AddressingMode combined_mode(const int mode, const int reg) {
|
2022-04-22 19:11:41 +00:00
|
|
|
|
assert(mode >= 0 && mode < 8);
|
|
|
|
|
assert(reg >= 0 && reg < 8);
|
|
|
|
|
|
|
|
|
|
// Look up mode, mapping invalid combinations to ::None, branchlessly.
|
|
|
|
|
const int use_reg = ((mode + 1) >> 3) & 1;
|
|
|
|
|
const AddressingMode modes[] = { AddressingMode(mode), extended_modes[reg] };
|
|
|
|
|
return modes[use_reg];
|
2022-04-11 19:00:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-25 20:23:16 +00:00
|
|
|
|
template <AddressingMode F> struct Mask {
|
|
|
|
|
static constexpr uint32_t value = uint32_t(1 << int(F));
|
2022-04-24 14:43:06 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static constexpr uint32_t NoOperand = Mask<AddressingMode::None>::value;
|
|
|
|
|
|
|
|
|
|
template <uint32_t first, uint32_t second> struct TwoOperandMask {
|
|
|
|
|
static constexpr uint32_t value = ((first << 16) & 0xffff0000) | (second & 0x0000ffff);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <uint32_t first> struct OneOperandMask {
|
|
|
|
|
static constexpr uint32_t value = TwoOperandMask<first, NoOperand>::value;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct NoOperandMask {
|
|
|
|
|
static constexpr uint32_t value = OneOperandMask<NoOperand>::value;
|
|
|
|
|
};
|
|
|
|
|
|
2024-10-14 01:34:01 +00:00
|
|
|
|
uint32_t operand_mask(const AddressingMode mode1, const AddressingMode mode2) {
|
2022-04-26 23:37:07 +00:00
|
|
|
|
return uint32_t((0x1'0000 << int(mode1)) | (0x0'0001 << int(mode2)));
|
2022-04-24 14:43:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-11 19:00:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - Instruction decoders.
|
|
|
|
|
|
2022-04-13 13:29:12 +00:00
|
|
|
|
/// Maps from an ExtendedOperation to an Operation; in practice that means that anything
|
|
|
|
|
/// that already is an Operation is passed through, and other things are mapped down into
|
|
|
|
|
/// an operation that doesn't duplicate detail about the operands that can be held by a
|
|
|
|
|
/// Preinstruction in other ways — for example, ANDI and AND are both represented by
|
|
|
|
|
/// a Preinstruction with an operation of AND, the former just happens to specify an
|
|
|
|
|
/// immediate operand.
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-10-14 01:34:01 +00:00
|
|
|
|
constexpr Operation Predecoder<model>::operation(const OpT op) {
|
2022-10-25 13:50:19 +00:00
|
|
|
|
if(op <= OpMax) {
|
2022-04-12 20:17:30 +00:00
|
|
|
|
return Operation(op);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch(op) {
|
|
|
|
|
case MOVEPtoRl: case MOVEPtoMl: return Operation::MOVEPl;
|
|
|
|
|
case MOVEPtoRw: case MOVEPtoMw: return Operation::MOVEPw;
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
case ADDQb: return Operation::ADDb;
|
|
|
|
|
case ADDQw: return Operation::ADDw;
|
|
|
|
|
case ADDQl: return Operation::ADDl;
|
|
|
|
|
case ADDQAw: return Operation::ADDAw;
|
|
|
|
|
case ADDQAl: return Operation::ADDAl;
|
|
|
|
|
case SUBQb: return Operation::SUBb;
|
2022-04-18 13:08:49 +00:00
|
|
|
|
case SUBQw: return Operation::SUBw;
|
|
|
|
|
case SUBQl: return Operation::SUBl;
|
2022-04-15 13:40:37 +00:00
|
|
|
|
case SUBQAw: return Operation::SUBAw;
|
|
|
|
|
case SUBQAl: return Operation::SUBAl;
|
|
|
|
|
|
2022-04-15 19:33:54 +00:00
|
|
|
|
case BTSTI: return Operation::BTST;
|
|
|
|
|
case BCHGI: return Operation::BCHG;
|
|
|
|
|
case BCLRI: return Operation::BCLR;
|
|
|
|
|
case BSETI: return Operation::BSET;
|
2022-04-15 13:40:37 +00:00
|
|
|
|
|
2022-04-22 13:24:16 +00:00
|
|
|
|
case CMPMb: return Operation::CMPb;
|
|
|
|
|
case CMPMw: return Operation::CMPw;
|
|
|
|
|
case CMPMl: return Operation::CMPl;
|
|
|
|
|
|
2022-04-18 11:42:30 +00:00
|
|
|
|
#define ImmediateGroup(x) \
|
|
|
|
|
case x##Ib: return Operation::x##b; \
|
|
|
|
|
case x##Iw: return Operation::x##w; \
|
|
|
|
|
case x##Il: return Operation::x##l;
|
|
|
|
|
|
|
|
|
|
ImmediateGroup(ADD)
|
|
|
|
|
ImmediateGroup(SUB);
|
|
|
|
|
ImmediateGroup(OR);
|
|
|
|
|
ImmediateGroup(AND);
|
|
|
|
|
ImmediateGroup(EOR);
|
|
|
|
|
ImmediateGroup(CMP);
|
|
|
|
|
|
|
|
|
|
#undef ImmediateGroup
|
|
|
|
|
|
2022-04-23 00:37:09 +00:00
|
|
|
|
case ADDtoRb: case ADDtoMb: return Operation::ADDb;
|
|
|
|
|
case ADDtoRw: case ADDtoMw: return Operation::ADDw;
|
|
|
|
|
case ADDtoRl: case ADDtoMl: return Operation::ADDl;
|
|
|
|
|
|
|
|
|
|
case SUBtoRb: case SUBtoMb: return Operation::SUBb;
|
|
|
|
|
case SUBtoRw: case SUBtoMw: return Operation::SUBw;
|
|
|
|
|
case SUBtoRl: case SUBtoMl: return Operation::SUBl;
|
|
|
|
|
|
|
|
|
|
case ANDtoRb: case ANDtoMb: return Operation::ANDb;
|
|
|
|
|
case ANDtoRw: case ANDtoMw: return Operation::ANDw;
|
|
|
|
|
case ANDtoRl: case ANDtoMl: return Operation::ANDl;
|
|
|
|
|
|
|
|
|
|
case ORtoRb: case ORtoMb: return Operation::ORb;
|
|
|
|
|
case ORtoRw: case ORtoMw: return Operation::ORw;
|
|
|
|
|
case ORtoRl: case ORtoMl: return Operation::ORl;
|
|
|
|
|
|
2022-04-25 23:58:19 +00:00
|
|
|
|
case EXGRtoR: case EXGAtoA: case EXGRtoA: return Operation::EXG;
|
|
|
|
|
|
|
|
|
|
case MOVEQ: return Operation::MOVEl;
|
2022-04-25 15:43:30 +00:00
|
|
|
|
|
2022-04-12 20:17:30 +00:00
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Operation::Undefined;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-24 14:43:06 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
template <typename Predecoder<model>::OpT op>
|
|
|
|
|
constexpr uint32_t Predecoder<model>::invalid_operands() {
|
2022-04-24 18:47:14 +00:00
|
|
|
|
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;
|
2022-10-22 19:20:30 +00:00
|
|
|
|
constexpr auto Ext = Mask< AddressingMode::ExtensionWord >::value;
|
2022-04-24 18:47:14 +00:00
|
|
|
|
|
2022-04-24 14:43:06 +00:00
|
|
|
|
// A few recurring combinations; terminology is directly from
|
|
|
|
|
// the Programmers' Reference Manual.
|
|
|
|
|
|
|
|
|
|
//
|
2022-04-24 18:47:14 +00:00
|
|
|
|
// All modes: the complete set (other than Quick).
|
2022-04-24 14:43:06 +00:00
|
|
|
|
//
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr auto AllModes = Dn | An | Ind | PostInc | PreDec | d16An |
|
|
|
|
|
d8AnXn | XXXw | XXXl | Imm | d16PC | d8PCXn;
|
|
|
|
|
constexpr auto AllModesNoAn = AllModes & ~An;
|
2022-04-24 14:43:06 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Alterable addressing modes (with and without AddressRegisterDirect).
|
|
|
|
|
//
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr auto AlterableAddressingModes = Dn | An | Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl;
|
|
|
|
|
constexpr auto AlterableAddressingModesNoAn = AlterableAddressingModes & ~An;
|
2022-04-24 14:43:06 +00:00
|
|
|
|
|
2022-04-25 16:30:44 +00:00
|
|
|
|
//
|
|
|
|
|
// Control [flow] addressing modes.
|
|
|
|
|
//
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr auto ControlAddressingModes = Ind | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn;
|
2022-10-25 13:50:19 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// An invalid response, used as the default case.
|
|
|
|
|
//
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr auto InvalidOperands = uint32_t(~0);
|
2022-04-25 16:30:44 +00:00
|
|
|
|
|
2022-04-24 14:43:06 +00:00
|
|
|
|
switch(op) {
|
2022-10-25 13:50:19 +00:00
|
|
|
|
default: break;
|
2022-04-24 14:43:06 +00:00
|
|
|
|
|
|
|
|
|
case OpT(Operation::ABCD):
|
|
|
|
|
case OpT(Operation::ADDXb): case OpT(Operation::ADDXw): case OpT(Operation::ADDXl):
|
2022-04-25 23:58:19 +00:00
|
|
|
|
case OpT(Operation::SBCD):
|
|
|
|
|
case OpT(Operation::SUBXb): case OpT(Operation::SUBXw): case OpT(Operation::SUBXl):
|
2022-04-24 18:47:14 +00:00
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Dn | PreDec,
|
|
|
|
|
Dn | PreDec
|
|
|
|
|
>::value;
|
2022-04-24 14:43:06 +00:00
|
|
|
|
|
|
|
|
|
case ADDtoRb:
|
2022-04-24 19:12:18 +00:00
|
|
|
|
case ANDtoRb: case ANDtoRw: case ANDtoRl:
|
2022-10-22 19:20:30 +00:00
|
|
|
|
case OpT(Operation::CHKw):
|
2022-04-25 01:05:00 +00:00
|
|
|
|
case OpT(Operation::CMPb):
|
2022-10-22 19:20:30 +00:00
|
|
|
|
case OpT(Operation::DIVUw): case OpT(Operation::DIVSw):
|
2022-04-25 19:43:25 +00:00
|
|
|
|
case ORtoRb: case ORtoRw: case ORtoRl:
|
2022-10-22 19:20:30 +00:00
|
|
|
|
case OpT(Operation::MULUw): case OpT(Operation::MULSw):
|
2022-04-25 16:41:41 +00:00
|
|
|
|
case SUBtoRb:
|
2022-04-24 14:43:06 +00:00
|
|
|
|
return ~TwoOperandMask<
|
2022-04-24 19:12:18 +00:00
|
|
|
|
AllModesNoAn,
|
2022-04-24 18:47:14 +00:00
|
|
|
|
Dn
|
|
|
|
|
>::value;
|
2022-04-24 14:43:06 +00:00
|
|
|
|
|
|
|
|
|
case ADDtoRw: case ADDtoRl:
|
2022-04-25 01:05:00 +00:00
|
|
|
|
case OpT(Operation::CMPw): case OpT(Operation::CMPl):
|
2022-04-25 16:41:41 +00:00
|
|
|
|
case SUBtoRw: case SUBtoRl:
|
2022-04-24 14:43:06 +00:00
|
|
|
|
return ~TwoOperandMask<
|
2022-04-24 18:47:14 +00:00
|
|
|
|
AllModes,
|
|
|
|
|
Dn
|
|
|
|
|
>::value;
|
2022-04-24 14:43:06 +00:00
|
|
|
|
|
|
|
|
|
case ADDtoMb: case ADDtoMw: case ADDtoMl:
|
2022-04-24 19:12:18 +00:00
|
|
|
|
case ANDtoMb: case ANDtoMw: case ANDtoMl:
|
2022-04-25 19:43:25 +00:00
|
|
|
|
case ORtoMb: case ORtoMw: case ORtoMl:
|
2022-04-25 16:41:41 +00:00
|
|
|
|
case SUBtoMb: case SUBtoMw: case SUBtoMl:
|
2022-04-24 18:47:14 +00:00
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Dn,
|
|
|
|
|
Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl
|
|
|
|
|
>::value;
|
2022-04-24 14:43:06 +00:00
|
|
|
|
|
2022-04-25 20:05:44 +00:00
|
|
|
|
case OpT(Operation::ADDAw): case OpT(Operation::ADDAl):
|
2023-05-12 18:14:45 +00:00
|
|
|
|
case OpT(Operation::CMPAw): case OpT(Operation::CMPAl):
|
2022-04-25 20:05:44 +00:00
|
|
|
|
case OpT(Operation::SUBAw): case OpT(Operation::SUBAl):
|
|
|
|
|
case OpT(Operation::MOVEAw): case OpT(Operation::MOVEAl):
|
2022-04-24 14:43:06 +00:00
|
|
|
|
return ~TwoOperandMask<
|
2022-04-24 18:47:14 +00:00
|
|
|
|
AllModes,
|
|
|
|
|
An
|
|
|
|
|
>::value;
|
2022-04-24 14:43:06 +00:00
|
|
|
|
|
|
|
|
|
case ADDIb: case ADDIl: case ADDIw:
|
2022-04-24 19:12:18 +00:00
|
|
|
|
case ANDIb: case ANDIl: case ANDIw:
|
2022-04-25 20:23:16 +00:00
|
|
|
|
case BCHGI: case BCLRI: case BSETI:
|
|
|
|
|
case EORIb: case EORIw: case EORIl:
|
|
|
|
|
case ORIb: case ORIw: case ORIl:
|
2022-04-25 16:41:41 +00:00
|
|
|
|
case SUBIb: case SUBIl: case SUBIw:
|
2022-04-24 18:47:14 +00:00
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Imm,
|
2022-04-24 19:12:18 +00:00
|
|
|
|
AlterableAddressingModesNoAn
|
2022-04-24 14:43:06 +00:00
|
|
|
|
>::value;
|
|
|
|
|
|
|
|
|
|
case ADDQb:
|
2022-04-25 16:41:41 +00:00
|
|
|
|
case SUBQb:
|
2022-04-24 18:47:14 +00:00
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Quick,
|
2022-04-24 19:12:18 +00:00
|
|
|
|
AlterableAddressingModesNoAn
|
2022-04-24 14:43:06 +00:00
|
|
|
|
>::value;
|
|
|
|
|
|
2022-04-25 23:58:19 +00:00
|
|
|
|
case MOVEQ:
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Quick,
|
|
|
|
|
Dn
|
|
|
|
|
>::value;
|
|
|
|
|
|
2022-04-24 14:43:06 +00:00
|
|
|
|
case ADDQw: case ADDQl:
|
2022-04-25 16:41:41 +00:00
|
|
|
|
case SUBQw: case SUBQl:
|
2022-04-24 18:47:14 +00:00
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Quick,
|
2022-05-03 18:17:26 +00:00
|
|
|
|
AlterableAddressingModesNoAn
|
|
|
|
|
>::value;
|
|
|
|
|
|
|
|
|
|
case ADDQAw: case ADDQAl:
|
|
|
|
|
case SUBQAw: case SUBQAl:
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Quick,
|
|
|
|
|
An
|
2022-04-24 14:43:06 +00:00
|
|
|
|
>::value;
|
|
|
|
|
|
2022-04-25 19:43:25 +00:00
|
|
|
|
case OpT(Operation::MOVEb):
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
AllModesNoAn,
|
|
|
|
|
AlterableAddressingModesNoAn
|
|
|
|
|
>::value;
|
|
|
|
|
|
|
|
|
|
case OpT(Operation::MOVEw): case OpT(Operation::MOVEl):
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
AllModes,
|
|
|
|
|
AlterableAddressingModesNoAn
|
|
|
|
|
>::value;
|
|
|
|
|
|
2022-04-25 16:30:44 +00:00
|
|
|
|
case OpT(Operation::ANDItoCCR): case OpT(Operation::ANDItoSR):
|
2022-10-25 13:50:19 +00:00
|
|
|
|
case OpT(Operation::Bccw): case OpT(Operation::BSRw):
|
2022-04-25 16:30:44 +00:00
|
|
|
|
case OpT(Operation::EORItoCCR): case OpT(Operation::EORItoSR):
|
|
|
|
|
case OpT(Operation::ORItoCCR): case OpT(Operation::ORItoSR):
|
|
|
|
|
case OpT(Operation::STOP):
|
2022-04-24 19:12:18 +00:00
|
|
|
|
return ~OneOperandMask<
|
|
|
|
|
Imm
|
|
|
|
|
>::value;
|
|
|
|
|
|
2022-04-24 23:53:54 +00:00
|
|
|
|
case OpT(Operation::ASLb): case OpT(Operation::ASLw): case OpT(Operation::ASLl):
|
|
|
|
|
case OpT(Operation::ASRb): case OpT(Operation::ASRw): case OpT(Operation::ASRl):
|
2022-04-25 16:30:44 +00:00
|
|
|
|
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):
|
2022-04-24 23:53:54 +00:00
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Quick | Dn,
|
|
|
|
|
Dn
|
|
|
|
|
>::value;
|
|
|
|
|
|
2022-04-25 16:30:44 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2022-04-24 23:53:54 +00:00
|
|
|
|
case OpT(Operation::Bccb):
|
2022-04-25 00:49:41 +00:00
|
|
|
|
case OpT(Operation::BSRb):
|
2022-04-25 16:30:44 +00:00
|
|
|
|
case OpT(Operation::TRAP):
|
2022-04-24 23:53:54 +00:00
|
|
|
|
return ~OneOperandMask<
|
|
|
|
|
Quick
|
|
|
|
|
>::value;
|
|
|
|
|
|
2022-04-24 23:58:10 +00:00
|
|
|
|
case OpT(Operation::BCHG):
|
|
|
|
|
case OpT(Operation::BCLR):
|
|
|
|
|
case OpT(Operation::BSET):
|
2022-04-25 13:49:18 +00:00
|
|
|
|
case OpT(Operation::EORb): case OpT(Operation::EORw): case OpT(Operation::EORl):
|
2022-04-24 23:53:54 +00:00
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Dn,
|
|
|
|
|
AlterableAddressingModesNoAn
|
|
|
|
|
>::value;
|
|
|
|
|
|
2022-04-25 00:49:41 +00:00
|
|
|
|
case OpT(Operation::BTST):
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Dn,
|
|
|
|
|
AllModesNoAn
|
|
|
|
|
>::value;
|
|
|
|
|
|
2022-04-25 13:39:22 +00:00
|
|
|
|
case CMPIb: case CMPIl: case CMPIw:
|
|
|
|
|
if constexpr (model == Model::M68000) {
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Imm,
|
|
|
|
|
Dn | Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl
|
|
|
|
|
>::value;
|
|
|
|
|
}
|
|
|
|
|
[[fallthrough]];
|
2022-04-25 00:49:41 +00:00
|
|
|
|
case BTSTI:
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Imm,
|
|
|
|
|
Dn | Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn
|
|
|
|
|
>::value;
|
|
|
|
|
|
2022-04-25 01:05:00 +00:00
|
|
|
|
case OpT(Operation::CLRb): case OpT(Operation::CLRw): case OpT(Operation::CLRl):
|
2022-04-24 14:43:06 +00:00
|
|
|
|
case OpT(Operation::NBCD):
|
2022-04-25 20:05:44 +00:00
|
|
|
|
case OpT(Operation::MOVEfromSR):
|
2022-04-25 20:23:16 +00:00
|
|
|
|
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):
|
2022-04-25 20:05:44 +00:00
|
|
|
|
case OpT(Operation::TAS):
|
2022-04-24 18:47:14 +00:00
|
|
|
|
return ~OneOperandMask<
|
2022-04-24 19:12:18 +00:00
|
|
|
|
AlterableAddressingModesNoAn
|
2022-04-24 18:47:14 +00:00
|
|
|
|
>::value;
|
2022-04-25 01:05:00 +00:00
|
|
|
|
|
2022-04-25 20:05:44 +00:00
|
|
|
|
case OpT(Operation::TSTb):
|
2022-10-27 13:49:20 +00:00
|
|
|
|
if constexpr (model < Model::M68020) {
|
2022-04-25 20:05:44 +00:00
|
|
|
|
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):
|
2022-10-27 13:49:20 +00:00
|
|
|
|
if constexpr (model < Model::M68020) {
|
2022-04-25 20:05:44 +00:00
|
|
|
|
return ~OneOperandMask<
|
|
|
|
|
AlterableAddressingModesNoAn
|
|
|
|
|
>::value;
|
|
|
|
|
} else {
|
|
|
|
|
return ~OneOperandMask<
|
|
|
|
|
AllModes
|
|
|
|
|
>::value;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-25 13:39:22 +00:00
|
|
|
|
case CMPMb: case CMPMw: case CMPMl:
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
PostInc,
|
|
|
|
|
PostInc
|
|
|
|
|
>::value;
|
|
|
|
|
|
2022-04-25 13:49:18 +00:00
|
|
|
|
case OpT(Operation::DBcc):
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Dn,
|
|
|
|
|
Imm
|
|
|
|
|
>::value;
|
|
|
|
|
|
2022-04-25 15:49:14 +00:00
|
|
|
|
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):
|
2022-04-25 16:30:44 +00:00
|
|
|
|
case OpT(Operation::SWAP):
|
2022-04-25 15:49:14 +00:00
|
|
|
|
return ~OneOperandMask<
|
|
|
|
|
Dn
|
|
|
|
|
>::value;
|
2022-04-25 16:05:07 +00:00
|
|
|
|
|
|
|
|
|
case OpT(Operation::JMP):
|
|
|
|
|
case OpT(Operation::JSR):
|
2022-04-25 16:41:41 +00:00
|
|
|
|
case OpT(Operation::PEA):
|
2022-04-25 16:05:07 +00:00
|
|
|
|
return ~OneOperandMask<
|
2022-04-25 16:30:44 +00:00
|
|
|
|
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):
|
2022-06-03 15:15:50 +00:00
|
|
|
|
case OpT(Operation::RESET):
|
2022-04-25 16:30:44 +00:00
|
|
|
|
return ~NoOperandMask::value;
|
|
|
|
|
|
|
|
|
|
case OpT(Operation::UNLINK):
|
|
|
|
|
case OpT(Operation::MOVEtoUSP):
|
|
|
|
|
case OpT(Operation::MOVEfromUSP):
|
|
|
|
|
return ~OneOperandMask<
|
|
|
|
|
An
|
2022-04-25 16:05:07 +00:00
|
|
|
|
>::value;
|
2022-04-25 20:23:16 +00:00
|
|
|
|
|
2022-05-06 13:45:06 +00:00
|
|
|
|
case OpT(Operation::MOVEMtoMw): case OpT(Operation::MOVEMtoMl):
|
2022-04-25 20:23:16 +00:00
|
|
|
|
return ~TwoOperandMask<
|
2022-10-22 19:20:30 +00:00
|
|
|
|
Ext,
|
2022-04-25 20:23:16 +00:00
|
|
|
|
Ind | PreDec | d16An | d8AnXn | XXXw | XXXl
|
|
|
|
|
>::value;
|
|
|
|
|
|
2022-05-06 13:45:06 +00:00
|
|
|
|
case OpT(Operation::MOVEMtoRw): case OpT(Operation::MOVEMtoRl):
|
2022-04-25 20:23:16 +00:00
|
|
|
|
return ~TwoOperandMask<
|
2022-10-22 19:20:30 +00:00
|
|
|
|
Ext,
|
2022-05-06 13:45:06 +00:00
|
|
|
|
Ind | PostInc | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn
|
2022-04-25 20:23:16 +00:00
|
|
|
|
>::value;
|
2022-04-25 23:58:19 +00:00
|
|
|
|
|
|
|
|
|
case MOVEPtoRl: case MOVEPtoRw:
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
d16An,
|
|
|
|
|
Dn
|
|
|
|
|
>::value;
|
|
|
|
|
|
|
|
|
|
case MOVEPtoMl: case MOVEPtoMw:
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Dn,
|
|
|
|
|
d16An
|
|
|
|
|
>::value;
|
2022-04-24 14:43:06 +00:00
|
|
|
|
}
|
2022-10-25 13:50:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// 68010 additions.
|
|
|
|
|
//
|
2022-10-26 02:36:00 +00:00
|
|
|
|
if constexpr (model < Model::M68010) {
|
2022-10-25 13:50:19 +00:00
|
|
|
|
return InvalidOperands;
|
|
|
|
|
}
|
|
|
|
|
switch(op) {
|
|
|
|
|
default: break;
|
|
|
|
|
|
|
|
|
|
case OpT(Operation::BKPT):
|
|
|
|
|
return ~OneOperandMask<
|
|
|
|
|
Quick
|
|
|
|
|
>::value;
|
|
|
|
|
|
|
|
|
|
case OpT(Operation::RTD):
|
|
|
|
|
return ~OneOperandMask<
|
|
|
|
|
Imm
|
|
|
|
|
>::value;
|
2022-10-26 16:39:40 +00:00
|
|
|
|
|
|
|
|
|
case OpT(Operation::MOVEfromCCR):
|
|
|
|
|
return ~OneOperandMask<
|
|
|
|
|
AlterableAddressingModesNoAn
|
|
|
|
|
>::value;
|
2022-10-26 16:50:15 +00:00
|
|
|
|
|
|
|
|
|
case OpT(Operation::MOVEfromC): case OpT(Operation::MOVEtoC):
|
|
|
|
|
return ~OneOperandMask<
|
|
|
|
|
Ext
|
|
|
|
|
>::value;
|
2022-10-26 17:34:01 +00:00
|
|
|
|
|
|
|
|
|
case OpT(Operation::MOVESb): case OpT(Operation::MOVESw): case OpT(Operation::MOVESl):
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Ext,
|
|
|
|
|
Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl
|
|
|
|
|
>::value;
|
2022-10-25 13:50:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// 68020 additions.
|
|
|
|
|
//
|
2022-10-26 02:36:00 +00:00
|
|
|
|
if constexpr (model < Model::M68020) {
|
2022-10-25 13:50:19 +00:00
|
|
|
|
return InvalidOperands;
|
|
|
|
|
}
|
|
|
|
|
switch(op) {
|
|
|
|
|
default: break;
|
|
|
|
|
|
2022-10-25 16:19:03 +00:00
|
|
|
|
case OpT(Operation::TRAPcc):
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Ext | NoOperand,
|
|
|
|
|
Ext | NoOperand
|
|
|
|
|
>::value;
|
|
|
|
|
|
2022-10-25 13:50:19 +00:00
|
|
|
|
case OpT(Operation::Bccl): case OpT(Operation::BSRl):
|
|
|
|
|
return ~OneOperandMask<
|
|
|
|
|
Imm
|
|
|
|
|
>::value;
|
|
|
|
|
|
|
|
|
|
case OpT(Operation::RTM):
|
|
|
|
|
return ~OneOperandMask<
|
|
|
|
|
An | Dn
|
|
|
|
|
>::value;
|
|
|
|
|
|
|
|
|
|
case OpT(Operation::CALLM):
|
|
|
|
|
return ~OneOperandMask<
|
|
|
|
|
ControlAddressingModes
|
|
|
|
|
>::value;
|
|
|
|
|
|
|
|
|
|
case OpT(Operation::BFCHG): case OpT(Operation::BFCLR): case OpT(Operation::BFSET):
|
|
|
|
|
case OpT(Operation::BFINS):
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Ext,
|
|
|
|
|
Dn | Ind | d16An | d8AnXn | XXXw | XXXl
|
|
|
|
|
>::value;
|
|
|
|
|
|
|
|
|
|
case OpT(Operation::BFTST): case OpT(Operation::BFFFO): case OpT(Operation::BFEXTU):
|
|
|
|
|
case OpT(Operation::BFEXTS):
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Ext,
|
|
|
|
|
Dn | Ind | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn
|
|
|
|
|
>::value;
|
|
|
|
|
|
2022-10-28 17:36:40 +00:00
|
|
|
|
case OpT(Operation::PACK): case OpT(Operation::UNPK):
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Dn | PreDec,
|
|
|
|
|
Dn | PreDec
|
2022-10-25 13:50:19 +00:00
|
|
|
|
>::value;
|
2022-10-28 17:57:00 +00:00
|
|
|
|
|
|
|
|
|
case OpT(Operation::CASb): case OpT(Operation::CASw): case OpT(Operation::CASl):
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Ext,
|
|
|
|
|
Ind | PostInc | PreDec | d16An | d8AnXn | XXXw | XXXl
|
|
|
|
|
>::value;
|
2022-10-28 18:02:49 +00:00
|
|
|
|
|
|
|
|
|
case OpT(Operation::CAS2w): case OpT(Operation::CAS2l):
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Ext,
|
|
|
|
|
Ext
|
|
|
|
|
>::value;
|
2022-10-30 01:32:48 +00:00
|
|
|
|
|
|
|
|
|
case OpT(Operation::CHKorCMP2b):
|
|
|
|
|
case OpT(Operation::CHKorCMP2w):
|
|
|
|
|
case OpT(Operation::CHKorCMP2l):
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Ext,
|
|
|
|
|
ControlAddressingModes
|
|
|
|
|
>::value;
|
2022-10-30 01:42:53 +00:00
|
|
|
|
|
|
|
|
|
case OpT(Operation::LINKl):
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
An,
|
|
|
|
|
Imm
|
|
|
|
|
>::value;
|
|
|
|
|
|
|
|
|
|
case OpT(Operation::CHKl):
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
AllModesNoAn,
|
|
|
|
|
Dn
|
|
|
|
|
>::value;
|
2022-10-30 15:20:43 +00:00
|
|
|
|
|
|
|
|
|
case OpT(Operation::EXTbtol):
|
|
|
|
|
return ~OneOperandMask<
|
|
|
|
|
Dn
|
|
|
|
|
>::value;
|
2022-10-30 15:32:36 +00:00
|
|
|
|
|
|
|
|
|
case OpT(Operation::DIVSorDIVUl):
|
|
|
|
|
case OpT(Operation::MULSorMULUl):
|
|
|
|
|
return ~TwoOperandMask<
|
|
|
|
|
Ext,
|
|
|
|
|
AllModesNoAn
|
|
|
|
|
>::value;
|
2022-10-25 13:50:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return InvalidOperands;
|
2022-04-24 14:43:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-19 18:36:36 +00:00
|
|
|
|
/// Provides a post-decoding validation step — primarily ensures that the prima facie addressing modes are supported by the operation.
|
2022-04-19 13:44:02 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
template <typename Predecoder<model>::OpT op, bool validate>
|
|
|
|
|
constexpr Preinstruction Predecoder<model>::validated(
|
2024-10-14 01:34:01 +00:00
|
|
|
|
const AddressingMode op1_mode, const int op1_reg,
|
|
|
|
|
const AddressingMode op2_mode, const int op2_reg,
|
|
|
|
|
const Condition condition,
|
|
|
|
|
const int additional_extension_words
|
2022-04-26 23:37:07 +00:00
|
|
|
|
) {
|
|
|
|
|
constexpr auto operation = Predecoder<model>::operation(op);
|
|
|
|
|
|
2022-04-19 13:59:02 +00:00
|
|
|
|
if constexpr (!validate) {
|
2022-04-26 23:37:07 +00:00
|
|
|
|
return Preinstruction(
|
|
|
|
|
operation,
|
|
|
|
|
op1_mode, op1_reg,
|
|
|
|
|
op2_mode, op2_reg,
|
2022-04-26 23:44:02 +00:00
|
|
|
|
requires_supervisor<model>(operation),
|
2022-10-28 17:36:40 +00:00
|
|
|
|
additional_extension_words,
|
2022-05-06 13:22:38 +00:00
|
|
|
|
operand_size(operation),
|
2022-04-30 13:00:47 +00:00
|
|
|
|
condition);
|
2022-04-19 13:59:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-25 20:23:16 +00:00
|
|
|
|
const auto invalid = invalid_operands<op>();
|
2022-04-26 23:37:07 +00:00
|
|
|
|
const auto observed = operand_mask(op1_mode, op2_mode);
|
|
|
|
|
return (observed & invalid) ?
|
|
|
|
|
Preinstruction() :
|
|
|
|
|
Preinstruction(
|
|
|
|
|
operation,
|
|
|
|
|
op1_mode, op1_reg,
|
|
|
|
|
op2_mode, op2_reg,
|
2022-04-26 23:44:02 +00:00
|
|
|
|
requires_supervisor<model>(operation),
|
2022-10-28 17:36:40 +00:00
|
|
|
|
additional_extension_words,
|
2022-05-06 13:22:38 +00:00
|
|
|
|
operand_size(operation),
|
2022-04-30 13:00:47 +00:00
|
|
|
|
condition);
|
2022-04-19 13:44:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
/// Decodes the fields within an instruction and constructs a `Preinstruction`, given that the operation has already been
|
|
|
|
|
/// decoded. Optionally applies validation
|
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
template <typename Predecoder<model>::OpT op, bool validate>
|
|
|
|
|
constexpr Preinstruction Predecoder<model>::decode(
|
|
|
|
|
const uint16_t instruction
|
|
|
|
|
) {
|
2022-04-11 19:00:55 +00:00
|
|
|
|
// Fields used pervasively below.
|
|
|
|
|
//
|
|
|
|
|
// Underlying assumption: the compiler will discard whatever of these
|
|
|
|
|
// isn't actually used.
|
|
|
|
|
const auto ea_register = instruction & 7;
|
|
|
|
|
const auto ea_mode = (instruction >> 3) & 7;
|
|
|
|
|
const auto opmode = (instruction >> 6) & 7;
|
|
|
|
|
const auto data_register = (instruction >> 9) & 7;
|
2022-04-15 20:01:33 +00:00
|
|
|
|
|
2022-10-25 13:50:19 +00:00
|
|
|
|
//
|
|
|
|
|
// Operations common to all processors.
|
|
|
|
|
//
|
2022-04-12 20:17:30 +00:00
|
|
|
|
switch(op) {
|
2022-10-25 13:50:19 +00:00
|
|
|
|
default: break;
|
2022-04-11 19:00:55 +00:00
|
|
|
|
|
|
|
|
|
//
|
2022-04-19 18:36:36 +00:00
|
|
|
|
// MARK: ABCD, SBCD, ADDX.
|
2022-04-11 19:00:55 +00:00
|
|
|
|
//
|
2022-04-18 12:00:43 +00:00
|
|
|
|
// b9–b11: Rx (destination)
|
|
|
|
|
// b0–b2: Ry (source)
|
|
|
|
|
// b3: 1 => operation is memory-to-memory; 0 => register-to-register.
|
|
|
|
|
//
|
2022-04-19 18:36:36 +00:00
|
|
|
|
case OpT(Operation::ABCD): case OpT(Operation::SBCD):
|
2022-04-19 20:27:20 +00:00
|
|
|
|
case OpT(Operation::ADDXb): case OpT(Operation::ADDXw): case OpT(Operation::ADDXl):
|
|
|
|
|
case OpT(Operation::SUBXb): case OpT(Operation::SUBXw): case OpT(Operation::SUBXl): {
|
2022-04-11 19:00:55 +00:00
|
|
|
|
const auto addressing_mode = (instruction & 8) ?
|
|
|
|
|
AddressingMode::AddressRegisterIndirectWithPredecrement : AddressingMode::DataRegisterDirect;
|
|
|
|
|
|
2022-04-19 13:44:02 +00:00
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
addressing_mode, ea_register,
|
|
|
|
|
addressing_mode, data_register);
|
2022-04-11 19:00:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// MARK: AND, OR, EOR.
|
|
|
|
|
//
|
2022-04-18 12:00:43 +00:00
|
|
|
|
// b9–b11: a register;
|
|
|
|
|
// b0–b2 and b3–b5: an effective address;
|
|
|
|
|
// b6–b8: an opmode, i.e. source + direction.
|
|
|
|
|
//
|
2022-04-23 00:37:09 +00:00
|
|
|
|
case ADDtoRb: case ADDtoRw: case ADDtoRl:
|
|
|
|
|
case SUBtoRb: case SUBtoRw: case SUBtoRl:
|
|
|
|
|
case ANDtoRb: case ANDtoRw: case ANDtoRl:
|
|
|
|
|
case ORtoRb: case ORtoRw: case ORtoRl:
|
2022-04-22 18:51:25 +00:00
|
|
|
|
case OpT(Operation::CMPb): case OpT(Operation::CMPw): case OpT(Operation::CMPl):
|
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register,
|
|
|
|
|
AddressingMode::DataRegisterDirect, data_register);
|
2022-04-22 18:51:25 +00:00
|
|
|
|
|
2022-04-23 00:37:09 +00:00
|
|
|
|
case ADDtoMb: case ADDtoMw: case ADDtoMl:
|
|
|
|
|
case SUBtoMb: case SUBtoMw: case SUBtoMl:
|
|
|
|
|
case ANDtoMb: case ANDtoMw: case ANDtoMl:
|
|
|
|
|
case ORtoMb: case ORtoMw: case ORtoMl:
|
2022-04-22 18:51:25 +00:00
|
|
|
|
case OpT(Operation::EORb): case OpT(Operation::EORw): case OpT(Operation::EORl):
|
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
AddressingMode::DataRegisterDirect, data_register,
|
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register);
|
2022-04-22 18:51:25 +00:00
|
|
|
|
|
|
|
|
|
case OpT(Operation::ADDAw): case OpT(Operation::ADDAl):
|
|
|
|
|
case OpT(Operation::SUBAw): case OpT(Operation::SUBAl):
|
|
|
|
|
case OpT(Operation::CMPAw): case OpT(Operation::CMPAl):
|
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register,
|
|
|
|
|
AddressingMode::AddressRegisterDirect, data_register);
|
2022-04-22 18:51:25 +00:00
|
|
|
|
|
2022-04-15 19:33:54 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: EORI, ORI, ANDI, SUBI, ADDI, CMPI, B[TST/CHG/CLR/SET]I
|
|
|
|
|
//
|
2022-04-18 12:00:43 +00:00
|
|
|
|
// Implicitly: source is an immediate value;
|
|
|
|
|
// b0–b2 and b3–b5: destination effective address.
|
|
|
|
|
//
|
2023-05-12 18:14:45 +00:00
|
|
|
|
case EORIb: case EORIl: case EORIw:
|
2022-04-15 19:33:54 +00:00
|
|
|
|
case ORIb: case ORIl: case ORIw:
|
|
|
|
|
case ANDIb: case ANDIl: case ANDIw:
|
|
|
|
|
case SUBIb: case SUBIl: case SUBIw:
|
|
|
|
|
case ADDIb: case ADDIl: case ADDIw:
|
|
|
|
|
case CMPIb: case CMPIl: case CMPIw:
|
|
|
|
|
case BTSTI: case BCHGI:
|
|
|
|
|
case BCLRI: case BSETI:
|
2022-04-19 13:44:02 +00:00
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
AddressingMode::ImmediateData, 0,
|
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register);
|
2022-04-15 19:33:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// MARK: BTST, BCLR, BCHG, BSET
|
|
|
|
|
//
|
2022-04-18 12:55:46 +00:00
|
|
|
|
// b0–b2 and b3–b5: destination effective address;
|
|
|
|
|
// b9–b11: source data register.
|
2022-04-18 12:00:43 +00:00
|
|
|
|
//
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case OpT(Operation::BTST): case OpT(Operation::BCLR):
|
|
|
|
|
case OpT(Operation::BCHG): case OpT(Operation::BSET):
|
2022-04-19 13:44:02 +00:00
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
AddressingMode::DataRegisterDirect, data_register,
|
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register);
|
2022-04-15 19:33:54 +00:00
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
//
|
2022-10-25 13:50:19 +00:00
|
|
|
|
// MARK: STOP, ANDItoCCR, ANDItoSR, EORItoCCR, EORItoSR, ORItoCCR, ORItoSR, BSRw
|
2022-04-15 13:40:37 +00:00
|
|
|
|
//
|
2022-04-30 13:00:47 +00:00
|
|
|
|
// Operand is an immedate; destination/source (if any) is implied by the operation,
|
|
|
|
|
// e.g. ORItoSR has a destination of SR.
|
2022-04-18 12:00:43 +00:00
|
|
|
|
//
|
2022-04-18 12:29:10 +00:00
|
|
|
|
case OpT(Operation::STOP):
|
2022-10-25 13:50:19 +00:00
|
|
|
|
case OpT(Operation::BSRw):
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case OpT(Operation::ORItoSR): case OpT(Operation::ORItoCCR):
|
|
|
|
|
case OpT(Operation::ANDItoSR): case OpT(Operation::ANDItoCCR):
|
|
|
|
|
case OpT(Operation::EORItoSR): case OpT(Operation::EORItoCCR):
|
2022-04-26 23:37:07 +00:00
|
|
|
|
return validated<op, validate>(AddressingMode::ImmediateData);
|
2022-04-15 13:40:37 +00:00
|
|
|
|
|
2022-04-30 13:00:47 +00:00
|
|
|
|
//
|
2022-10-25 13:50:19 +00:00
|
|
|
|
// MARK: Bccw
|
2022-04-30 13:00:47 +00:00
|
|
|
|
//
|
|
|
|
|
// Operand is an immedate; b8–b11 are a condition code.
|
|
|
|
|
//
|
2022-10-25 13:50:19 +00:00
|
|
|
|
case OpT(Operation::Bccw):
|
2022-04-30 13:00:47 +00:00
|
|
|
|
return validated<op, validate>(
|
|
|
|
|
AddressingMode::ImmediateData, 0,
|
|
|
|
|
AddressingMode::None, 0,
|
|
|
|
|
Condition((instruction >> 8) & 0xf));
|
|
|
|
|
|
2022-04-18 12:00:43 +00:00
|
|
|
|
//
|
2022-10-30 01:42:53 +00:00
|
|
|
|
// MARK: CHKw
|
2022-04-18 12:00:43 +00:00
|
|
|
|
//
|
|
|
|
|
// Implicitly: destination is a register;
|
|
|
|
|
// b0–b2 and b3–b5: source effective address.
|
|
|
|
|
//
|
2022-10-22 19:20:30 +00:00
|
|
|
|
case OpT(Operation::CHKw):
|
2022-04-19 13:44:02 +00:00
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register,
|
|
|
|
|
AddressingMode::DataRegisterDirect, data_register);
|
2022-04-18 12:00:43 +00:00
|
|
|
|
|
2022-04-11 19:00:55 +00:00
|
|
|
|
//
|
2022-10-25 13:50:19 +00:00
|
|
|
|
// MARK: EXG
|
2022-04-11 19:00:55 +00:00
|
|
|
|
//
|
2022-04-18 12:00:43 +00:00
|
|
|
|
// b0–b2: register Ry (data or address, address if exchange is address <-> data);
|
|
|
|
|
// b9–b11: register Rx (data or address, data if exchange is address <-> data);
|
|
|
|
|
// b3–b7: an opmode, indicating address/data registers.
|
|
|
|
|
//
|
2022-04-25 15:43:30 +00:00
|
|
|
|
case EXGRtoR:
|
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
AddressingMode::DataRegisterDirect, data_register,
|
|
|
|
|
AddressingMode::DataRegisterDirect, ea_register);
|
2022-04-11 19:00:55 +00:00
|
|
|
|
|
2022-04-25 15:43:30 +00:00
|
|
|
|
case EXGAtoA:
|
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
AddressingMode::AddressRegisterDirect, data_register,
|
|
|
|
|
AddressingMode::AddressRegisterDirect, ea_register);
|
2022-04-11 19:00:55 +00:00
|
|
|
|
|
2022-04-25 15:43:30 +00:00
|
|
|
|
case EXGRtoA:
|
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
AddressingMode::DataRegisterDirect, data_register,
|
|
|
|
|
AddressingMode::AddressRegisterDirect, ea_register);
|
2022-04-11 19:00:55 +00:00
|
|
|
|
|
|
|
|
|
//
|
2022-04-11 20:32:57 +00:00
|
|
|
|
// MARK: MULU, MULS, DIVU, DIVS.
|
2022-04-11 19:00:55 +00:00
|
|
|
|
//
|
2022-04-18 12:00:43 +00:00
|
|
|
|
// b9–b11: destination data register;
|
|
|
|
|
// b0–b2 and b3–b5: source effective address.
|
|
|
|
|
//
|
2022-10-22 19:20:30 +00:00
|
|
|
|
case OpT(Operation::DIVUw): case OpT(Operation::DIVSw):
|
|
|
|
|
case OpT(Operation::MULUw): case OpT(Operation::MULSw):
|
2022-04-19 13:44:02 +00:00
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register,
|
|
|
|
|
AddressingMode::DataRegisterDirect, data_register);
|
2022-04-11 19:00:55 +00:00
|
|
|
|
|
2022-04-18 12:00:43 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: LEA
|
|
|
|
|
//
|
|
|
|
|
// b9–b11: destination address register;
|
|
|
|
|
// b0–b2 and b3–b5: source effective address.
|
|
|
|
|
//
|
2022-04-19 23:36:21 +00:00
|
|
|
|
case OpT(Operation::LEA):
|
2022-04-19 13:44:02 +00:00
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register,
|
|
|
|
|
AddressingMode::AddressRegisterDirect, data_register);
|
2022-04-18 12:00:43 +00:00
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: MOVEPtoRw, MOVEPtoRl
|
|
|
|
|
//
|
2022-04-18 12:00:43 +00:00
|
|
|
|
// b0–b2: an address register;
|
|
|
|
|
// b9–b11: a data register.
|
|
|
|
|
// [already decoded: b6–b8: an opmode, indicating size and direction]
|
|
|
|
|
//
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case OpT(MOVEPtoRw): case OpT(MOVEPtoRl):
|
2022-04-19 13:44:02 +00:00
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
AddressingMode::AddressRegisterIndirectWithDisplacement, ea_register,
|
|
|
|
|
AddressingMode::DataRegisterDirect, data_register);
|
2022-04-12 18:54:11 +00:00
|
|
|
|
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case OpT(MOVEPtoMw): case OpT(MOVEPtoMl):
|
2022-04-19 13:44:02 +00:00
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
AddressingMode::DataRegisterDirect, data_register,
|
|
|
|
|
AddressingMode::AddressRegisterIndirectWithDisplacement, ea_register);
|
2022-04-12 18:54:11 +00:00
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
//
|
2022-04-15 19:40:31 +00:00
|
|
|
|
// MARK: MOVE
|
2022-04-15 13:40:37 +00:00
|
|
|
|
//
|
2022-04-18 12:00:43 +00:00
|
|
|
|
// b0–b2 and b3–b5: source effective address;
|
|
|
|
|
// b6–b8 and b9–b11: destination effective address;
|
|
|
|
|
// [already decoded: b12–b13: size]
|
|
|
|
|
//
|
2022-04-19 21:13:23 +00:00
|
|
|
|
case OpT(Operation::MOVEb): case OpT(Operation::MOVEl): case OpT(Operation::MOVEw):
|
|
|
|
|
case OpT(Operation::MOVEAl): case OpT(Operation::MOVEAw):
|
2022-04-19 13:44:02 +00:00
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register,
|
|
|
|
|
combined_mode(opmode, data_register), data_register);
|
2022-04-15 19:40:31 +00:00
|
|
|
|
|
|
|
|
|
//
|
2022-04-18 12:29:10 +00:00
|
|
|
|
// MARK: RESET, NOP RTE, RTS, TRAPV, RTR
|
2022-04-15 19:40:31 +00:00
|
|
|
|
//
|
2022-04-18 12:00:43 +00:00
|
|
|
|
// No additional fields.
|
|
|
|
|
//
|
2022-04-18 12:29:10 +00:00
|
|
|
|
case OpT(Operation::RESET): case OpT(Operation::NOP):
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case OpT(Operation::RTE): case OpT(Operation::RTS): case OpT(Operation::TRAPV):
|
|
|
|
|
case OpT(Operation::RTR):
|
2022-04-26 23:37:07 +00:00
|
|
|
|
return validated<op, validate>();
|
2022-04-15 13:40:37 +00:00
|
|
|
|
|
2022-04-15 20:01:33 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: NEGX, CLR, NEG, MOVEtoCCR, MOVEtoSR, NOT, NBCD, PEA, TST
|
|
|
|
|
//
|
2022-04-18 12:00:43 +00:00
|
|
|
|
// b0–b2 and b3–b5: effective address.
|
|
|
|
|
//
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case OpT(Operation::CLRb): case OpT(Operation::CLRw): case OpT(Operation::CLRl):
|
|
|
|
|
case OpT(Operation::JMP): case OpT(Operation::JSR):
|
|
|
|
|
case OpT(Operation::MOVEtoSR): case OpT(Operation::MOVEfromSR): case OpT(Operation::MOVEtoCCR):
|
|
|
|
|
case OpT(Operation::NBCD):
|
|
|
|
|
case OpT(Operation::NEGb): case OpT(Operation::NEGw): case OpT(Operation::NEGl):
|
|
|
|
|
case OpT(Operation::NEGXb): case OpT(Operation::NEGXw): case OpT(Operation::NEGXl):
|
|
|
|
|
case OpT(Operation::NOTb): case OpT(Operation::NOTw): case OpT(Operation::NOTl):
|
|
|
|
|
case OpT(Operation::PEA):
|
|
|
|
|
case OpT(Operation::TAS):
|
|
|
|
|
case OpT(Operation::TSTb): case OpT(Operation::TSTw): case OpT(Operation::TSTl):
|
2022-04-26 23:37:07 +00:00
|
|
|
|
return validated<op, validate>(combined_mode(ea_mode, ea_register), ea_register);
|
2022-04-15 20:01:33 +00:00
|
|
|
|
|
2022-04-30 13:00:47 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: Scc
|
|
|
|
|
//
|
|
|
|
|
// b0–b2 and b3–b5: effective address;
|
|
|
|
|
// b8–b11: a condition.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::Scc):
|
|
|
|
|
return validated<op, validate>(
|
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register,
|
|
|
|
|
AddressingMode::None, 0,
|
|
|
|
|
Condition((instruction >> 8) & 0xf));
|
|
|
|
|
|
2022-04-18 12:29:10 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: UNLINK, MOVEtoUSP, MOVEfromUSP
|
|
|
|
|
//
|
|
|
|
|
// b0–b2: an address register.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::UNLINK):
|
|
|
|
|
case OpT(Operation::MOVEfromUSP): case OpT(Operation::MOVEtoUSP):
|
2022-04-26 23:37:07 +00:00
|
|
|
|
return validated<op, validate>(AddressingMode::AddressRegisterDirect, ea_register);
|
2022-04-18 12:29:10 +00:00
|
|
|
|
|
2022-04-18 12:55:46 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: DBcc
|
|
|
|
|
//
|
2022-04-30 13:00:47 +00:00
|
|
|
|
// b0–b2: a data register;
|
|
|
|
|
// b8–b11: a condition.
|
2022-04-18 12:55:46 +00:00
|
|
|
|
// Followed by an immediate value.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::DBcc):
|
2022-04-19 13:44:02 +00:00
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
AddressingMode::DataRegisterDirect, ea_register,
|
2022-04-30 13:00:47 +00:00
|
|
|
|
AddressingMode::ImmediateData, 0,
|
|
|
|
|
Condition((instruction >> 8) & 0xf));
|
2022-04-18 12:55:46 +00:00
|
|
|
|
|
2022-04-19 12:37:13 +00:00
|
|
|
|
//
|
2022-04-19 12:42:17 +00:00
|
|
|
|
// MARK: SWAP, EXTbtow, EXTwtol
|
2022-04-19 12:37:13 +00:00
|
|
|
|
//
|
|
|
|
|
// b0–b2: a data register.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::SWAP):
|
2022-04-19 12:42:17 +00:00
|
|
|
|
case OpT(Operation::EXTbtow): case OpT(Operation::EXTwtol):
|
2022-04-26 23:37:07 +00:00
|
|
|
|
return validated<op, validate>(AddressingMode::DataRegisterDirect, ea_register);
|
2022-04-19 12:37:13 +00:00
|
|
|
|
|
2022-04-15 20:01:33 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: MOVEMtoMw, MOVEMtoMl, MOVEMtoRw, MOVEMtoRl
|
|
|
|
|
//
|
2022-04-18 12:00:43 +00:00
|
|
|
|
// b0–b2 and b3–b5: effective address.
|
|
|
|
|
// [already decoded: b10: direction]
|
|
|
|
|
//
|
2022-05-06 13:45:06 +00:00
|
|
|
|
case OpT(Operation::MOVEMtoMl): case OpT(Operation::MOVEMtoMw):
|
|
|
|
|
case OpT(Operation::MOVEMtoRl): case OpT(Operation::MOVEMtoRw):
|
2022-04-19 13:44:02 +00:00
|
|
|
|
return validated<op, validate>(
|
2022-10-22 19:20:30 +00:00
|
|
|
|
AddressingMode::ExtensionWord, 0,
|
2022-04-26 23:37:07 +00:00
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register);
|
2022-04-15 20:01:33 +00:00
|
|
|
|
|
2022-04-18 12:05:33 +00:00
|
|
|
|
//
|
2022-10-25 13:50:19 +00:00
|
|
|
|
// MARK: TRAP, BCCb, BSRb
|
2022-04-18 12:05:33 +00:00
|
|
|
|
//
|
2022-10-21 19:28:29 +00:00
|
|
|
|
// No further operands decoded, but one is somewhere in the opcode.
|
2022-04-18 12:05:33 +00:00
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::TRAP):
|
2022-04-18 12:55:46 +00:00
|
|
|
|
case OpT(Operation::BSRb):
|
2022-04-26 23:37:07 +00:00
|
|
|
|
return validated<op, validate>(AddressingMode::Quick);
|
2022-04-18 12:05:33 +00:00
|
|
|
|
|
2022-05-03 19:32:54 +00:00
|
|
|
|
case OpT(Operation::Bccb):
|
|
|
|
|
return validated<op, validate>(
|
|
|
|
|
AddressingMode::Quick, 0,
|
|
|
|
|
AddressingMode::None, 0,
|
|
|
|
|
Condition((instruction >> 8) & 0xf));
|
|
|
|
|
|
2022-04-18 12:29:10 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: LINKw
|
|
|
|
|
//
|
2022-04-18 12:55:46 +00:00
|
|
|
|
// b0–b2: 'source' address register;
|
2022-04-18 12:29:10 +00:00
|
|
|
|
// Implicitly: 'destination' is an immediate.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::LINKw):
|
2022-04-19 13:44:02 +00:00
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
AddressingMode::AddressRegisterDirect, ea_register,
|
|
|
|
|
AddressingMode::ImmediateData, 0);
|
2022-04-18 12:29:10 +00:00
|
|
|
|
|
2022-04-18 12:55:46 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: ADDQ, SUBQ
|
|
|
|
|
//
|
|
|
|
|
// b0–b2 and b3–5: a destination effective address;
|
|
|
|
|
// b9–b11: an immediate value, embedded in the opcode.
|
|
|
|
|
//
|
|
|
|
|
case ADDQb: case ADDQw: case ADDQl:
|
2022-05-03 18:17:26 +00:00
|
|
|
|
case ADDQAw: case ADDQAl:
|
2022-04-18 12:55:46 +00:00
|
|
|
|
case SUBQb: case SUBQw: case SUBQl:
|
2022-05-03 18:17:26 +00:00
|
|
|
|
case SUBQAw: case SUBQAl:
|
2022-04-19 13:44:02 +00:00
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
AddressingMode::Quick, 0,
|
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register);
|
2022-04-18 12:55:46 +00:00
|
|
|
|
|
2022-04-18 13:12:45 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: MOVEq
|
|
|
|
|
//
|
|
|
|
|
// b9–b11: a destination register;
|
|
|
|
|
// b0–b7: a 'quick' value.
|
|
|
|
|
//
|
2022-04-25 23:58:19 +00:00
|
|
|
|
case MOVEQ:
|
2022-04-19 13:44:02 +00:00
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
AddressingMode::Quick, 0,
|
|
|
|
|
AddressingMode::DataRegisterDirect, data_register);
|
2022-04-18 13:12:45 +00:00
|
|
|
|
|
2022-04-18 18:41:26 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: ASR, LSR, ROXR, ROR, ASL, LSL, ROXL, ROL
|
|
|
|
|
//
|
|
|
|
|
// b0–b2: a register to shift (the source here, for consistency with the memory operations);
|
2024-12-01 14:00:29 +00:00
|
|
|
|
// b8: 0 => b9–b11 are a direct count of bits to shift;
|
|
|
|
|
// 1 => b9–b11 identify register containing the shift count;
|
2022-04-18 18:41:26 +00:00
|
|
|
|
// b9–b11: either a quick value or a register.
|
2022-10-21 19:28:29 +00:00
|
|
|
|
//
|
2022-04-18 18:41:26 +00:00
|
|
|
|
case OpT(Operation::ASRb): case OpT(Operation::ASRw): case OpT(Operation::ASRl):
|
|
|
|
|
case OpT(Operation::LSRb): case OpT(Operation::LSRw): case OpT(Operation::LSRl):
|
|
|
|
|
case OpT(Operation::ROXRb): case OpT(Operation::ROXRw): case OpT(Operation::ROXRl):
|
|
|
|
|
case OpT(Operation::RORb): case OpT(Operation::RORw): case OpT(Operation::RORl):
|
|
|
|
|
case OpT(Operation::ASLb): case OpT(Operation::ASLw): case OpT(Operation::ASLl):
|
|
|
|
|
case OpT(Operation::LSLb): case OpT(Operation::LSLw): case OpT(Operation::LSLl):
|
|
|
|
|
case OpT(Operation::ROXLb): case OpT(Operation::ROXLw): case OpT(Operation::ROXLl):
|
|
|
|
|
case OpT(Operation::ROLb): case OpT(Operation::ROLw): case OpT(Operation::ROLl):
|
2022-04-19 13:44:02 +00:00
|
|
|
|
return validated<op, validate>(
|
2022-04-26 23:37:07 +00:00
|
|
|
|
(instruction & 0x20) ? AddressingMode::DataRegisterDirect : AddressingMode::Quick, data_register,
|
|
|
|
|
AddressingMode::DataRegisterDirect, ea_register);
|
2022-04-18 18:41:26 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// MARK: ASRm, LSRm, ROXRm, RORm, ASLm, LSLm, ROXLm, ROLm
|
|
|
|
|
//
|
|
|
|
|
// b0–b2 and b3–5: an effective address.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::ASRm): case OpT(Operation::ASLm):
|
|
|
|
|
case OpT(Operation::LSRm): case OpT(Operation::LSLm):
|
|
|
|
|
case OpT(Operation::ROXRm): case OpT(Operation::ROXLm):
|
|
|
|
|
case OpT(Operation::RORm): case OpT(Operation::ROLm):
|
2022-04-26 23:37:07 +00:00
|
|
|
|
return validated<op, validate>(combined_mode(ea_mode, ea_register), ea_register);
|
2022-04-18 18:41:26 +00:00
|
|
|
|
|
2022-04-22 13:24:16 +00:00
|
|
|
|
case CMPMb: case CMPMw: case CMPMl:
|
|
|
|
|
return validated<op, validate>(
|
|
|
|
|
AddressingMode::AddressRegisterIndirectWithPostincrement, ea_register,
|
2022-04-26 23:37:07 +00:00
|
|
|
|
AddressingMode::AddressRegisterIndirectWithPostincrement, data_register);
|
2022-10-25 13:50:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// 68010 additions.
|
|
|
|
|
//
|
|
|
|
|
if constexpr (model < Model::M68010) {
|
|
|
|
|
assert(false);
|
|
|
|
|
}
|
|
|
|
|
switch(op) {
|
|
|
|
|
default: break;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// MARK: BKPT
|
|
|
|
|
//
|
|
|
|
|
// No further operands decoded, but one is somewhere in the opcode.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::BKPT):
|
|
|
|
|
return validated<op, validate>(AddressingMode::Quick);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// MARK: RTD
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::RTD):
|
|
|
|
|
return validated<op, validate>(AddressingMode::ImmediateData);
|
2022-10-26 16:39:40 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// MARK: MOVE from CCR.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::MOVEfromCCR):
|
|
|
|
|
return validated<op, validate>(combined_mode(ea_mode, ea_register), ea_register);
|
2022-10-26 16:50:15 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// MARK: MOVE to/from C.
|
|
|
|
|
//
|
|
|
|
|
// No further information in the instruction, but an extension word is required.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::MOVEfromC): case OpT(Operation::MOVEtoC):
|
|
|
|
|
return validated<op, validate>(AddressingMode::ExtensionWord);
|
2022-10-26 17:34:01 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// MARK: MOVES
|
|
|
|
|
//
|
|
|
|
|
// b0–b2 and b3–b5: effective address;
|
2022-10-30 01:32:48 +00:00
|
|
|
|
// also an extension word is present to dictate a further register and a direction of transfer.
|
2022-10-26 17:34:01 +00:00
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::MOVESb): case OpT(Operation::MOVESw): case OpT(Operation::MOVESl):
|
|
|
|
|
return validated<op, validate>(
|
|
|
|
|
AddressingMode::ExtensionWord, 0,
|
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register);
|
2022-10-25 13:50:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// 68020 additions.
|
|
|
|
|
//
|
|
|
|
|
if constexpr (model < Model::M68020) {
|
|
|
|
|
assert(false);
|
|
|
|
|
}
|
|
|
|
|
switch(op) {
|
|
|
|
|
default: break;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// MARK: BSRl
|
|
|
|
|
//
|
|
|
|
|
// Operand is an immedate.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::BSRl):
|
|
|
|
|
return validated<op, validate>(AddressingMode::ImmediateData);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// MARK: Bccl
|
|
|
|
|
//
|
|
|
|
|
// Operand is an immedate; b8–b11 are a condition code.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::Bccl):
|
|
|
|
|
return validated<op, validate>(
|
|
|
|
|
AddressingMode::ImmediateData, 0,
|
|
|
|
|
AddressingMode::None, 0,
|
|
|
|
|
Condition((instruction >> 8) & 0xf));
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// MARK: DIVSl.
|
|
|
|
|
//
|
|
|
|
|
// b0–b2 and b3–b5: source effective address.
|
|
|
|
|
// Plus an immediate word operand
|
|
|
|
|
//
|
2022-10-30 15:32:36 +00:00
|
|
|
|
case OpT(Operation::DIVSorDIVUl):
|
|
|
|
|
case OpT(Operation::MULSorMULUl):
|
2022-10-25 13:50:19 +00:00
|
|
|
|
return validated<op, validate>(
|
|
|
|
|
AddressingMode::ExtensionWord, 0,
|
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register);
|
2022-04-22 13:24:16 +00:00
|
|
|
|
|
2022-10-21 19:28:29 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: BFCHG, BFTST, BFFFO, BFEXTU, BFEXTS, BFCLR, BFSET, BFINS
|
|
|
|
|
//
|
|
|
|
|
// b0–b2 and b3–b5: an effective address.
|
|
|
|
|
// There is also an immedate operand describing an offset and width.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::BFCHG): case OpT(Operation::BFTST): case OpT(Operation::BFFFO):
|
|
|
|
|
case OpT(Operation::BFEXTU): case OpT(Operation::BFEXTS): case OpT(Operation::BFCLR):
|
|
|
|
|
case OpT(Operation::BFSET): case OpT(Operation::BFINS):
|
|
|
|
|
return validated<op, validate>(
|
2022-10-23 15:46:47 +00:00
|
|
|
|
AddressingMode::ExtensionWord, 0,
|
2022-10-21 19:28:29 +00:00
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// MARK: CALLM
|
|
|
|
|
//
|
|
|
|
|
// b0–b2 and b3–b5: an effective address.
|
|
|
|
|
// There is also an immedate operand providing argument count.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::CALLM):
|
|
|
|
|
return validated<op, validate>(
|
|
|
|
|
AddressingMode::ImmediateData, 0,
|
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register);
|
|
|
|
|
|
2022-10-22 19:20:30 +00:00
|
|
|
|
//
|
|
|
|
|
// 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<op, validate>(addressing_mode, ea_register);
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-25 16:19:03 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: TRAPcc
|
|
|
|
|
//
|
|
|
|
|
// Has 0, 1 or 2 following words, neither of which contributes to operation.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::TRAPcc): {
|
|
|
|
|
switch(instruction & 7) {
|
|
|
|
|
default: return Preinstruction();
|
|
|
|
|
|
|
|
|
|
// No extension.
|
|
|
|
|
case 4: return validated<op, validate>();
|
|
|
|
|
|
|
|
|
|
// Word-sized extension.
|
|
|
|
|
case 2: return validated<op, validate>(AddressingMode::ExtensionWord);
|
|
|
|
|
|
|
|
|
|
// DWord-sized extension (which is encoded as two extension operands).
|
|
|
|
|
case 3:
|
|
|
|
|
return validated<op, validate>(
|
|
|
|
|
AddressingMode::ExtensionWord, 0,
|
|
|
|
|
AddressingMode::ExtensionWord, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 15:46:47 +00:00
|
|
|
|
//
|
2022-10-28 17:36:40 +00:00
|
|
|
|
// MARK: PACK, UNPK
|
2022-10-23 15:46:47 +00:00
|
|
|
|
//
|
2022-10-28 17:36:40 +00:00
|
|
|
|
// b9–b11: Rx (destination)
|
|
|
|
|
// b0–b2: Ry (source)
|
|
|
|
|
// b3: 1 => operation is memory-to-memory; 0 => register-to-register.
|
2022-10-23 15:46:47 +00:00
|
|
|
|
// This instruction is also followed by a 16-bit adjustment extension.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::PACK):
|
2022-10-28 17:36:40 +00:00
|
|
|
|
case OpT(Operation::UNPK): {
|
|
|
|
|
const auto addressing_mode = (instruction & 8) ?
|
|
|
|
|
AddressingMode::AddressRegisterIndirectWithPredecrement : AddressingMode::DataRegisterDirect;
|
2022-10-23 15:46:47 +00:00
|
|
|
|
|
2022-10-28 17:36:40 +00:00
|
|
|
|
return validated<op, validate>(
|
|
|
|
|
addressing_mode, ea_register,
|
|
|
|
|
addressing_mode, data_register,
|
|
|
|
|
Condition::True, 1);
|
|
|
|
|
}
|
2022-10-25 16:19:03 +00:00
|
|
|
|
|
2022-10-28 17:57:00 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: CAS
|
|
|
|
|
//
|
|
|
|
|
// b0–b2 and b3–b5: an effective address.
|
|
|
|
|
// There is also an immedate operand describing relevant registers.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::CASb): case OpT(Operation::CASw): case OpT(Operation::CASl):
|
2022-10-30 01:32:48 +00:00
|
|
|
|
case OpT(Operation::CHKorCMP2b):
|
|
|
|
|
case OpT(Operation::CHKorCMP2w):
|
|
|
|
|
case OpT(Operation::CHKorCMP2l):
|
2022-10-28 17:57:00 +00:00
|
|
|
|
return validated<op, validate>(
|
|
|
|
|
AddressingMode::ExtensionWord, 0,
|
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register);
|
|
|
|
|
|
2022-10-28 18:02:49 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: CAS2
|
|
|
|
|
//
|
|
|
|
|
// b0–b2 and b3–b5: an effective address.
|
|
|
|
|
// There is also an immedate operand describing relevant registers.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::CAS2w): case OpT(Operation::CAS2l):
|
|
|
|
|
return validated<op, validate>(
|
|
|
|
|
AddressingMode::ExtensionWord, 0,
|
|
|
|
|
AddressingMode::ExtensionWord, 0);
|
|
|
|
|
|
2022-10-30 01:42:53 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: LINKl
|
|
|
|
|
//
|
|
|
|
|
// b0–b2: 'source' address register;
|
|
|
|
|
// Implicitly: 'destination' is an immediate.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::LINKl):
|
|
|
|
|
return validated<op, validate>(
|
|
|
|
|
AddressingMode::AddressRegisterDirect, ea_register,
|
|
|
|
|
AddressingMode::ImmediateData, 0);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// MARK: CHKl
|
|
|
|
|
//
|
|
|
|
|
// Implicitly: destination is a register;
|
|
|
|
|
// b0–b2 and b3–b5: source effective address.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::CHKl):
|
|
|
|
|
return validated<op, validate>(
|
|
|
|
|
combined_mode(ea_mode, ea_register), ea_register,
|
|
|
|
|
AddressingMode::DataRegisterDirect, data_register);
|
|
|
|
|
|
2022-10-30 15:20:43 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: EXTbtol
|
|
|
|
|
//
|
|
|
|
|
// b0–b2: a data register.
|
|
|
|
|
//
|
|
|
|
|
case OpT(Operation::EXTbtol):
|
|
|
|
|
return validated<op, validate>(AddressingMode::DataRegisterDirect, ea_register);
|
|
|
|
|
|
2022-10-22 19:20:30 +00:00
|
|
|
|
//
|
|
|
|
|
// MARK: DIVl
|
|
|
|
|
//
|
|
|
|
|
//
|
2022-10-25 13:50:19 +00:00
|
|
|
|
// TODO.
|
2022-04-11 19:00:55 +00:00
|
|
|
|
}
|
2022-10-25 13:50:19 +00:00
|
|
|
|
|
|
|
|
|
// Should be unreachable.
|
|
|
|
|
assert(false);
|
2022-10-25 14:20:06 +00:00
|
|
|
|
return Preinstruction(); // To appease GCC during development.
|
2022-04-11 19:00:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - Page decoders.
|
|
|
|
|
|
2024-12-01 13:20:24 +00:00
|
|
|
|
#define Decode(y) return decode<OpT(y)>(instruction)
|
2022-10-21 19:28:29 +00:00
|
|
|
|
#define DecodeReq(x, y) if constexpr (x) Decode(y); break;
|
2022-04-12 20:17:30 +00:00
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decode0(const uint16_t instruction) {
|
2022-04-16 00:33:59 +00:00
|
|
|
|
using Op = Operation;
|
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
switch(instruction & 0xfff) {
|
2022-04-16 00:41:39 +00:00
|
|
|
|
case 0x03c: Decode(Op::ORItoCCR); // 4-155 (p259)
|
|
|
|
|
case 0x07c: Decode(Op::ORItoSR); // 6-27 (p481)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x23c: Decode(Op::ANDItoCCR); // 4-20 (p124)
|
2022-04-16 00:41:39 +00:00
|
|
|
|
case 0x27c: Decode(Op::ANDItoSR); // 6-2 (p456)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0xa3c: Decode(Op::EORItoCCR); // 4-104 (p208)
|
2022-04-16 00:41:39 +00:00
|
|
|
|
case 0xa7c: Decode(Op::EORItoSR); // 6-10 (p464)
|
2022-04-12 18:54:11 +00:00
|
|
|
|
|
2022-10-22 19:20:30 +00:00
|
|
|
|
// 4-68 (p172)
|
2022-10-28 18:02:49 +00:00
|
|
|
|
case 0xcfc: DecodeReq(model >= Model::M68020, Op::CAS2w);
|
|
|
|
|
case 0xefc: DecodeReq(model >= Model::M68020, Op::CAS2l);
|
2022-10-22 19:20:30 +00:00
|
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch(instruction & 0xff0) {
|
|
|
|
|
case 0x6c0: DecodeReq(model == Model::M68020, Op::RTM); // 4-167 (p271)
|
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-12 12:36:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch(instruction & 0xfc0) {
|
|
|
|
|
// 4-153 (p257)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x000: Decode(ORIb);
|
|
|
|
|
case 0x040: Decode(ORIw);
|
|
|
|
|
case 0x080: Decode(ORIl);
|
2022-04-12 12:36:44 +00:00
|
|
|
|
|
|
|
|
|
// 4-18 (p122)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x200: Decode(ANDIb);
|
|
|
|
|
case 0x240: Decode(ANDIw);
|
|
|
|
|
case 0x280: Decode(ANDIl);
|
2022-04-12 12:36:44 +00:00
|
|
|
|
|
|
|
|
|
// 4-179 (p283)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x400: Decode(SUBIb);
|
|
|
|
|
case 0x440: Decode(SUBIw);
|
|
|
|
|
case 0x480: Decode(SUBIl);
|
2022-04-12 12:36:44 +00:00
|
|
|
|
|
|
|
|
|
// 4-9 (p113)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x600: Decode(ADDIb);
|
|
|
|
|
case 0x640: Decode(ADDIw);
|
|
|
|
|
case 0x680: Decode(ADDIl);
|
2022-04-12 12:36:44 +00:00
|
|
|
|
|
|
|
|
|
// 4-63 (p167)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x800: Decode(BTSTI);
|
2022-04-12 12:36:44 +00:00
|
|
|
|
|
|
|
|
|
// 4-29 (p133)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x840: Decode(BCHGI);
|
2022-04-12 12:36:44 +00:00
|
|
|
|
|
|
|
|
|
// 4-32 (p136)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x880: Decode(BCLRI);
|
2022-04-12 12:36:44 +00:00
|
|
|
|
|
|
|
|
|
// 4-58 (p162)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x8c0: Decode(BSETI);
|
2022-04-12 12:36:44 +00:00
|
|
|
|
|
|
|
|
|
// 4-102 (p206)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0xa00: Decode(EORIb);
|
|
|
|
|
case 0xa40: Decode(EORIw);
|
|
|
|
|
case 0xa80: Decode(EORIl);
|
2022-04-12 12:36:44 +00:00
|
|
|
|
|
|
|
|
|
// 4-79 (p183)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0xc00: Decode(CMPIb);
|
|
|
|
|
case 0xc40: Decode(CMPIw);
|
|
|
|
|
case 0xc80: Decode(CMPIl);
|
2022-04-12 12:36:44 +00:00
|
|
|
|
|
2022-10-22 19:20:30 +00:00
|
|
|
|
// 4-64 (p168)
|
|
|
|
|
case 0x6c0: DecodeReq(model == Model::M68020, Op::CALLM);
|
|
|
|
|
|
|
|
|
|
// 4-67 (p171)
|
2022-10-28 17:57:00 +00:00
|
|
|
|
case 0xac0: DecodeReq(model >= Model::M68020, Op::CASb);
|
|
|
|
|
case 0xcc0: DecodeReq(model >= Model::M68020, Op::CASw);
|
|
|
|
|
case 0xec0: DecodeReq(model >= Model::M68020, Op::CASl);
|
2022-10-22 19:20:30 +00:00
|
|
|
|
|
2022-10-30 01:32:48 +00:00
|
|
|
|
// 4-83 (p187) [CMP2] and 4-72 (p176) [CHK2];
|
|
|
|
|
// the two are distinguished by a bit in the extension word.
|
|
|
|
|
case 0x0c0: DecodeReq(model >= Model::M68020, Op::CHKorCMP2b);
|
|
|
|
|
case 0x2c0: DecodeReq(model >= Model::M68020, Op::CHKorCMP2b);
|
|
|
|
|
case 0x4c0: DecodeReq(model >= Model::M68020, Op::CHKorCMP2b);
|
2022-10-26 17:34:01 +00:00
|
|
|
|
|
|
|
|
|
// 6-24 (p478)
|
|
|
|
|
case 0xe00: DecodeReq(model >= Model::M68010, Op::MOVESb);
|
|
|
|
|
case 0xe40: DecodeReq(model >= Model::M68010, Op::MOVESw);
|
|
|
|
|
case 0xe80: DecodeReq(model >= Model::M68010, Op::MOVESl);
|
2022-10-21 19:28:29 +00:00
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-12 12:36:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch(instruction & 0x1f8) {
|
|
|
|
|
// 4-133 (p237)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x108: Decode(MOVEPtoRw);
|
|
|
|
|
case 0x148: Decode(MOVEPtoRl);
|
|
|
|
|
case 0x188: Decode(MOVEPtoMw);
|
|
|
|
|
case 0x1c8: Decode(MOVEPtoMl);
|
2022-04-12 12:36:44 +00:00
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-12 12:36:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-20 12:40:56 +00:00
|
|
|
|
switch(instruction & 0x1c0) {
|
|
|
|
|
case 0x100: Decode(Op::BTST); // 4-62 (p166)
|
|
|
|
|
case 0x180: Decode(Op::BCLR); // 4-31 (p135)
|
|
|
|
|
|
|
|
|
|
case 0x140: Decode(Op::BCHG); // 4-28 (p132)
|
|
|
|
|
case 0x1c0: Decode(Op::BSET); // 4-57 (p161)
|
|
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-12 12:16:29 +00:00
|
|
|
|
return Preinstruction();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decode1(const uint16_t instruction) {
|
2022-04-16 00:33:59 +00:00
|
|
|
|
using Op = Operation;
|
|
|
|
|
|
2022-04-15 19:40:31 +00:00
|
|
|
|
// 4-116 (p220)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
Decode(Op::MOVEb);
|
2022-04-12 12:16:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decode2(const uint16_t instruction) {
|
2022-04-16 00:33:59 +00:00
|
|
|
|
using Op = Operation;
|
|
|
|
|
|
2022-04-15 19:40:31 +00:00
|
|
|
|
// 4-116 (p220)
|
2022-04-19 21:13:23 +00:00
|
|
|
|
switch(instruction & 0x1c0) {
|
|
|
|
|
case 0x040: Decode(Op::MOVEAl);
|
|
|
|
|
default: Decode(Op::MOVEl);
|
|
|
|
|
}
|
2022-04-12 12:16:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decode3(const uint16_t instruction) {
|
2022-04-16 00:33:59 +00:00
|
|
|
|
using Op = Operation;
|
|
|
|
|
|
2022-04-15 19:40:31 +00:00
|
|
|
|
// 4-116 (p220)
|
2022-04-19 21:13:23 +00:00
|
|
|
|
switch(instruction & 0x1c0) {
|
|
|
|
|
case 0x040: Decode(Op::MOVEAw);
|
|
|
|
|
default: Decode(Op::MOVEw);
|
|
|
|
|
}
|
2022-04-12 12:16:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decode4(const uint16_t instruction) {
|
2022-04-16 00:33:59 +00:00
|
|
|
|
using Op = Operation;
|
|
|
|
|
|
2022-04-12 11:49:08 +00:00
|
|
|
|
switch(instruction & 0xfff) {
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0xe70: Decode(Op::RESET); // 6-83 (p537)
|
|
|
|
|
case 0xe71: Decode(Op::NOP); // 4-147 (p251)
|
2022-04-18 12:29:10 +00:00
|
|
|
|
case 0xe72: Decode(Op::STOP); // 6-85 (p539)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0xe73: Decode(Op::RTE); // 6-84 (p538)
|
2022-10-21 19:28:29 +00:00
|
|
|
|
case 0xe74: DecodeReq(model >= Model::M68010, Op::RTD); // 4-166 (p270)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0xe75: Decode(Op::RTS); // 4-169 (p273)
|
|
|
|
|
case 0xe76: Decode(Op::TRAPV); // 4-191 (p295)
|
|
|
|
|
case 0xe77: Decode(Op::RTR); // 4-168 (p272)
|
2022-10-26 16:50:15 +00:00
|
|
|
|
case 0xe7a: DecodeReq(model >= Model::M68010, Op::MOVEtoC); // 6-22 (p476)
|
|
|
|
|
case 0xe7b: DecodeReq(model >= Model::M68010, Op::MOVEfromC); // 6-22 (p476)
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-12 11:49:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-19 12:00:52 +00:00
|
|
|
|
switch(instruction & 0xff8) {
|
2022-04-20 00:28:00 +00:00
|
|
|
|
case 0x840: Decode(Op::SWAP); // 4-185 (p289)
|
2022-10-21 19:28:29 +00:00
|
|
|
|
case 0x848: DecodeReq(model >= Model::M68010, Op::BKPT); // 4-54 (p158)
|
2022-04-19 12:00:52 +00:00
|
|
|
|
case 0xe58: Decode(Op::UNLINK); // 4-194 (p298)
|
|
|
|
|
case 0xe60: Decode(Op::MOVEtoUSP); // 6-21 (p475)
|
|
|
|
|
case 0xe68: Decode(Op::MOVEfromUSP); // 6-21 (p475)
|
2022-10-30 01:42:53 +00:00
|
|
|
|
|
2022-10-30 15:20:43 +00:00
|
|
|
|
// 4-106 (p210)
|
|
|
|
|
case 0x880: Decode(Op::EXTbtow);
|
|
|
|
|
case 0x8c0: Decode(Op::EXTwtol);
|
|
|
|
|
case 0x9c0: DecodeReq(model >= Model::M68020, Op::EXTbtol);
|
|
|
|
|
|
2022-10-30 01:42:53 +00:00
|
|
|
|
// 4-111 (p215)
|
|
|
|
|
case 0x808: DecodeReq(model >= Model::M68020, Op::LINKl);
|
|
|
|
|
case 0xe50: Decode(Op::LINKw);
|
|
|
|
|
|
2022-04-19 12:00:52 +00:00
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch(instruction & 0xff0) {
|
|
|
|
|
case 0xe40: Decode(Op::TRAP); // 4-188 (p292)
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-12 11:49:08 +00:00
|
|
|
|
switch(instruction & 0xfc0) {
|
|
|
|
|
// 4-146 (p250)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x000: Decode(Op::NEGXb);
|
|
|
|
|
case 0x040: Decode(Op::NEGXw);
|
|
|
|
|
case 0x080: Decode(Op::NEGXl);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
|
|
|
|
// 6-17 (p471)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x0c0: Decode(Op::MOVEfromSR);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
|
|
|
|
// 4-73 (p177)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x200: Decode(Op::CLRb);
|
|
|
|
|
case 0x240: Decode(Op::CLRw);
|
|
|
|
|
case 0x280: Decode(Op::CLRl);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
2022-04-15 20:01:33 +00:00
|
|
|
|
// 4-144 (p247)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x400: Decode(Op::NEGb);
|
|
|
|
|
case 0x440: Decode(Op::NEGw);
|
|
|
|
|
case 0x480: Decode(Op::NEGl);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
|
|
|
|
// 4-123 (p227)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x4c0: Decode(Op::MOVEtoCCR);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
2022-04-15 20:01:33 +00:00
|
|
|
|
// 4-148 (p252)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x600: Decode(Op::NOTb);
|
|
|
|
|
case 0x640: Decode(Op::NOTw);
|
|
|
|
|
case 0x680: Decode(Op::NOTl);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
|
|
|
|
// 4-123 (p227)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x6c0: Decode(Op::MOVEtoSR);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
|
|
|
|
// 4-142 (p246)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x800: Decode(Op::NBCD);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
|
|
|
|
// 4-159 (p263)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x840: Decode(Op::PEA);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
|
|
|
|
// 4-128 (p232)
|
2022-05-06 13:45:06 +00:00
|
|
|
|
case 0x880: Decode(Op::MOVEMtoMw);
|
|
|
|
|
case 0x8c0: Decode(Op::MOVEMtoMl);
|
|
|
|
|
case 0xc80: Decode(Op::MOVEMtoRw);
|
|
|
|
|
case 0xcc0: Decode(Op::MOVEMtoRl);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
|
|
|
|
// 4-192 (p296)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0xa00: Decode(Op::TSTb);
|
|
|
|
|
case 0xa40: Decode(Op::TSTw);
|
|
|
|
|
case 0xa80: Decode(Op::TSTl);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
|
|
|
|
// 4-186 (p290)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0xac0: Decode(Op::TAS);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
|
|
|
|
// 4-109 (p213)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0xe80: Decode(Op::JSR);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
|
|
|
|
// 4-108 (p212)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0xec0: Decode(Op::JMP);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
2022-10-30 15:32:36 +00:00
|
|
|
|
// 4-94 (p198) [DIVS.l]; 4-98 (p202) [DIVU.l]
|
|
|
|
|
case 0xc40: DecodeReq(model >= Model::M68020, Op::DIVSorDIVUl);
|
|
|
|
|
|
|
|
|
|
// 4-137 (p241) [MULS.l]; 4-140 (p244) [MULU.l]
|
|
|
|
|
case 0xc00: DecodeReq(model >= Model::M68020, Op::MULSorMULUl);
|
2022-10-22 19:20:30 +00:00
|
|
|
|
|
2022-10-26 16:39:40 +00:00
|
|
|
|
// 4-121 (p225)
|
|
|
|
|
case 0x2c0: DecodeReq(model >= Model::M68010, Op::MOVEfromCCR);
|
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-12 11:49:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch(instruction & 0x1c0) {
|
2022-04-19 23:36:21 +00:00
|
|
|
|
case 0x1c0: Decode(Op::LEA); // 4-110 (p214)
|
2022-10-30 01:42:53 +00:00
|
|
|
|
|
|
|
|
|
// 4-69 (p173)
|
|
|
|
|
case 0x180: Decode(Op::CHKw);
|
|
|
|
|
case 0x100: DecodeReq(model >= Model::M68020, Op::CHKl);
|
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-12 11:49:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Preinstruction();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decode5(const uint16_t instruction) {
|
2022-04-16 00:33:59 +00:00
|
|
|
|
using Op = Operation;
|
|
|
|
|
|
2022-05-03 18:17:26 +00:00
|
|
|
|
switch(instruction & 0x1f8) {
|
2022-04-12 12:44:32 +00:00
|
|
|
|
// 4-11 (p115)
|
2022-05-03 18:17:26 +00:00
|
|
|
|
case 0x000:
|
|
|
|
|
case 0x010: case 0x018:
|
|
|
|
|
case 0x020: case 0x028:
|
|
|
|
|
case 0x030: case 0x038:
|
|
|
|
|
Decode(ADDQb);
|
|
|
|
|
|
|
|
|
|
case 0x040:
|
|
|
|
|
case 0x050: case 0x058:
|
|
|
|
|
case 0x060: case 0x068:
|
|
|
|
|
case 0x070: case 0x078:
|
|
|
|
|
Decode(ADDQw);
|
|
|
|
|
|
|
|
|
|
case 0x080:
|
|
|
|
|
case 0x090: case 0x098:
|
|
|
|
|
case 0x0a0: case 0x0a8:
|
|
|
|
|
case 0x0b0: case 0x0b8:
|
|
|
|
|
Decode(ADDQl);
|
|
|
|
|
|
|
|
|
|
case 0x048: Decode(ADDQAw);
|
|
|
|
|
case 0x088: Decode(ADDQAl);
|
2022-04-12 12:44:32 +00:00
|
|
|
|
|
|
|
|
|
// 4-181 (p285)
|
2022-05-03 18:17:26 +00:00
|
|
|
|
case 0x100:
|
|
|
|
|
case 0x110: case 0x118:
|
|
|
|
|
case 0x120: case 0x128:
|
|
|
|
|
case 0x130: case 0x138:
|
|
|
|
|
Decode(SUBQb);
|
|
|
|
|
|
|
|
|
|
case 0x140:
|
|
|
|
|
case 0x150: case 0x158:
|
|
|
|
|
case 0x160: case 0x168:
|
|
|
|
|
case 0x170: case 0x178:
|
|
|
|
|
Decode(SUBQw);
|
|
|
|
|
|
|
|
|
|
case 0x180:
|
|
|
|
|
case 0x190: case 0x198:
|
|
|
|
|
case 0x1a0: case 0x1a8:
|
|
|
|
|
case 0x1b0: case 0x1b8:
|
|
|
|
|
Decode(SUBQl);
|
|
|
|
|
|
|
|
|
|
case 0x148: Decode(SUBQAw);
|
|
|
|
|
case 0x188: Decode(SUBQAl);
|
2022-04-12 12:44:32 +00:00
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-12 12:44:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 15:46:47 +00:00
|
|
|
|
switch(instruction & 0x0ff) {
|
|
|
|
|
// 4-173 (p276)
|
|
|
|
|
case 0x0f8: case 0x0f9: Decode(Op::Scc);
|
|
|
|
|
|
|
|
|
|
// 4-189 (p294)
|
|
|
|
|
case 0x0fa: case 0x0fb: case 0x0fc:
|
|
|
|
|
DecodeReq(model >= Model::M68020, Op::TRAPcc);
|
|
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-18 12:55:46 +00:00
|
|
|
|
switch(instruction & 0x0f8) {
|
|
|
|
|
// 4-173 (p276)
|
|
|
|
|
case 0x0c0:
|
2022-04-18 13:04:17 +00:00
|
|
|
|
case 0x0d0: case 0x0d8:
|
2022-04-18 12:55:46 +00:00
|
|
|
|
case 0x0e0: case 0x0e8:
|
2022-10-23 15:46:47 +00:00
|
|
|
|
case 0x0f0: Decode(Op::Scc);
|
2022-04-18 12:55:46 +00:00
|
|
|
|
|
|
|
|
|
// 4-91 (p195)
|
|
|
|
|
case 0x0c8: Decode(Op::DBcc);
|
2022-04-12 12:44:32 +00:00
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-12 12:44:32 +00:00
|
|
|
|
}
|
2022-04-12 12:16:29 +00:00
|
|
|
|
return Preinstruction();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decode6(const uint16_t instruction) {
|
2022-04-16 00:33:59 +00:00
|
|
|
|
using Op = Operation;
|
|
|
|
|
|
2022-04-18 12:55:46 +00:00
|
|
|
|
switch(instruction & 0xf00) {
|
|
|
|
|
// 4-59 (p163)
|
2022-04-21 20:24:34 +00:00
|
|
|
|
case 0x100:
|
2022-04-18 12:55:46 +00:00
|
|
|
|
switch(instruction & 0xff) {
|
|
|
|
|
case 0x00: Decode(Op::BSRw);
|
|
|
|
|
case 0xff:
|
2022-04-18 18:42:31 +00:00
|
|
|
|
if constexpr (model >= Model::M68020) {
|
2022-04-18 12:55:46 +00:00
|
|
|
|
Decode(Op::BSRl);
|
|
|
|
|
}
|
|
|
|
|
[[fallthrough]];
|
|
|
|
|
default: Decode(Op::BSRb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4-25 (p129) Bcc
|
|
|
|
|
// 4-55 (p159) BRA (i.e. Bcc with cc = always)
|
|
|
|
|
default:
|
|
|
|
|
switch(instruction & 0xff) {
|
|
|
|
|
case 0x00: Decode(Op::Bccw);
|
|
|
|
|
case 0xff:
|
2022-04-18 18:42:31 +00:00
|
|
|
|
if constexpr (model >= Model::M68020) {
|
2022-04-18 12:55:46 +00:00
|
|
|
|
Decode(Op::Bccl);
|
|
|
|
|
}
|
|
|
|
|
[[fallthrough]];
|
|
|
|
|
default: Decode(Op::Bccb);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-04-12 12:16:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decode7(const uint16_t instruction) {
|
2022-04-12 12:44:32 +00:00
|
|
|
|
// 4-134 (p238)
|
2022-04-21 20:05:00 +00:00
|
|
|
|
if(!(instruction & 0x100)) {
|
2022-04-25 23:58:19 +00:00
|
|
|
|
Decode(MOVEQ);
|
2022-04-21 20:05:00 +00:00
|
|
|
|
} else {
|
|
|
|
|
return Preinstruction();
|
|
|
|
|
}
|
2022-04-12 12:16:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decode8(const uint16_t instruction) {
|
2022-04-16 00:33:59 +00:00
|
|
|
|
using Op = Operation;
|
|
|
|
|
|
2022-10-23 15:46:47 +00:00
|
|
|
|
switch(instruction & 0x1f0) {
|
|
|
|
|
case 0x100: Decode(Op::SBCD); // 4-171 (p275)
|
2022-10-27 14:52:07 +00:00
|
|
|
|
case 0x140: DecodeReq(model >= Model::M68020, Op::PACK); // 4-157 (p261)
|
2022-10-28 17:36:40 +00:00
|
|
|
|
case 0x180: DecodeReq(model >= Model::M68020, Op::UNPK); // 4-196 (p300)
|
2022-10-23 15:46:47 +00:00
|
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
2022-04-11 20:32:57 +00:00
|
|
|
|
|
|
|
|
|
switch(instruction & 0x1c0) {
|
2022-10-22 19:20:30 +00:00
|
|
|
|
case 0x0c0: Decode(Op::DIVUw); // 4-97 (p201)
|
|
|
|
|
case 0x1c0: Decode(Op::DIVSw); // 4-93 (p197)
|
2022-04-23 00:37:09 +00:00
|
|
|
|
|
|
|
|
|
// 4-150 (p254)
|
|
|
|
|
case 0x000: Decode(ORtoRb);
|
|
|
|
|
case 0x040: Decode(ORtoRw);
|
|
|
|
|
case 0x080: Decode(ORtoRl);
|
|
|
|
|
case 0x100: Decode(ORtoMb);
|
|
|
|
|
case 0x140: Decode(ORtoMw);
|
|
|
|
|
case 0x180: Decode(ORtoMl);
|
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-11 20:32:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Preinstruction();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decode9(const uint16_t instruction) {
|
2022-04-16 00:33:59 +00:00
|
|
|
|
using Op = Operation;
|
|
|
|
|
|
2022-04-19 20:27:20 +00:00
|
|
|
|
switch(instruction & 0x1f0) {
|
|
|
|
|
// 4-184 (p288)
|
|
|
|
|
case 0x100: Decode(Op::SUBXb);
|
|
|
|
|
case 0x140: Decode(Op::SUBXw);
|
|
|
|
|
case 0x180: Decode(Op::SUBXl);
|
2022-04-12 12:57:40 +00:00
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-12 12:57:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch(instruction & 0x1c0) {
|
|
|
|
|
// 4-177 (p281)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x0c0: Decode(Op::SUBAw);
|
|
|
|
|
case 0x1c0: Decode(Op::SUBAl);
|
2022-04-12 12:57:40 +00:00
|
|
|
|
|
2022-04-19 20:27:20 +00:00
|
|
|
|
// 4-174 (p278)
|
2022-04-23 00:37:09 +00:00
|
|
|
|
case 0x000: Decode(SUBtoRb);
|
|
|
|
|
case 0x040: Decode(SUBtoRw);
|
|
|
|
|
case 0x080: Decode(SUBtoRl);
|
|
|
|
|
case 0x100: Decode(SUBtoMb);
|
|
|
|
|
case 0x140: Decode(SUBtoMw);
|
|
|
|
|
case 0x180: Decode(SUBtoMl);
|
2022-04-12 12:57:40 +00:00
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-12 12:57:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-12 12:16:29 +00:00
|
|
|
|
return Preinstruction();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decodeA(const uint16_t) {
|
2022-04-12 12:16:29 +00:00
|
|
|
|
return Preinstruction();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decodeB(const uint16_t instruction) {
|
2022-04-16 00:33:59 +00:00
|
|
|
|
using Op = Operation;
|
|
|
|
|
|
2022-04-22 13:24:16 +00:00
|
|
|
|
switch(instruction & 0x1f8) {
|
|
|
|
|
// 4-81 (p185)
|
|
|
|
|
case 0x108: Decode(CMPMb);
|
|
|
|
|
case 0x148: Decode(CMPMw);
|
|
|
|
|
case 0x188: Decode(CMPMl);
|
|
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-12 11:49:08 +00:00
|
|
|
|
switch(instruction & 0x1c0) {
|
2022-04-12 12:57:40 +00:00
|
|
|
|
// 4-75 (p179)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x000: Decode(Op::CMPb);
|
|
|
|
|
case 0x040: Decode(Op::CMPw);
|
|
|
|
|
case 0x080: Decode(Op::CMPl);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
|
|
|
|
// 4-77 (p181)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x0c0: Decode(Op::CMPAw);
|
|
|
|
|
case 0x1c0: Decode(Op::CMPAl);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
2022-04-22 00:14:52 +00:00
|
|
|
|
// 4-100 (p204)
|
2022-04-22 00:36:04 +00:00
|
|
|
|
case 0x100: Decode(Op::EORb);
|
|
|
|
|
case 0x140: Decode(Op::EORw);
|
|
|
|
|
case 0x180: Decode(Op::EORl);
|
|
|
|
|
|
2022-04-22 00:14:52 +00:00
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-12 11:49:08 +00:00
|
|
|
|
return Preinstruction();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decodeC(const uint16_t instruction) {
|
2022-04-16 00:33:59 +00:00
|
|
|
|
using Op = Operation;
|
|
|
|
|
|
2022-04-22 00:14:52 +00:00
|
|
|
|
// 4-105 (p209)
|
|
|
|
|
switch(instruction & 0x1f8) {
|
2022-04-25 15:43:30 +00:00
|
|
|
|
case 0x140: Decode(EXGRtoR);
|
|
|
|
|
case 0x148: Decode(EXGAtoA);
|
|
|
|
|
case 0x188: Decode(EXGRtoA);
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-12 13:08:46 +00:00
|
|
|
|
}
|
2022-04-11 19:00:55 +00:00
|
|
|
|
|
2022-04-22 00:14:52 +00:00
|
|
|
|
switch(instruction & 0x1f0) {
|
|
|
|
|
case 0x100: Decode(Op::ABCD); // 4-3 (p107)
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-11 19:00:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch(instruction & 0x1c0) {
|
2022-10-22 19:20:30 +00:00
|
|
|
|
case 0x0c0: Decode(Op::MULUw); // 4-139 (p243)
|
|
|
|
|
case 0x1c0: Decode(Op::MULSw); // 4-136 (p240)
|
2022-04-11 19:00:55 +00:00
|
|
|
|
|
2022-04-22 00:14:52 +00:00
|
|
|
|
// 4-15 (p119)
|
2022-04-23 00:37:09 +00:00
|
|
|
|
case 0x000: Decode(ANDtoRb);
|
|
|
|
|
case 0x040: Decode(ANDtoRw);
|
|
|
|
|
case 0x080: Decode(ANDtoRl);
|
|
|
|
|
case 0x100: Decode(ANDtoMb);
|
|
|
|
|
case 0x140: Decode(ANDtoMw);
|
|
|
|
|
case 0x180: Decode(ANDtoMl);
|
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-11 19:00:55 +00:00
|
|
|
|
}
|
2022-04-12 11:49:08 +00:00
|
|
|
|
|
2022-04-11 19:00:55 +00:00
|
|
|
|
return Preinstruction();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decodeD(const uint16_t instruction) {
|
2022-04-16 00:33:59 +00:00
|
|
|
|
using Op = Operation;
|
|
|
|
|
|
2022-04-19 18:36:36 +00:00
|
|
|
|
switch(instruction & 0x1f0) {
|
|
|
|
|
// 4-14 (p118)
|
|
|
|
|
case 0x100: Decode(Op::ADDXb);
|
|
|
|
|
case 0x140: Decode(Op::ADDXw);
|
|
|
|
|
case 0x180: Decode(Op::ADDXl);
|
2022-04-12 12:57:40 +00:00
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-12 12:57:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch(instruction & 0x1c0) {
|
|
|
|
|
// 4-7 (p111)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x0c0: Decode(Op::ADDAw);
|
|
|
|
|
case 0x1c0: Decode(Op::ADDAl);
|
2022-04-12 12:57:40 +00:00
|
|
|
|
|
2022-04-19 18:36:36 +00:00
|
|
|
|
// 4-4 (p108)
|
2022-04-23 00:37:09 +00:00
|
|
|
|
case 0x000: Decode(ADDtoRb);
|
|
|
|
|
case 0x040: Decode(ADDtoRw);
|
|
|
|
|
case 0x080: Decode(ADDtoRl);
|
|
|
|
|
case 0x100: Decode(ADDtoMb);
|
|
|
|
|
case 0x140: Decode(ADDtoMw);
|
|
|
|
|
case 0x180: Decode(ADDtoMl);
|
2022-04-12 12:57:40 +00:00
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-12 12:57:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-12 12:16:29 +00:00
|
|
|
|
return Preinstruction();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decodeE(const uint16_t instruction) {
|
2022-04-16 00:33:59 +00:00
|
|
|
|
using Op = Operation;
|
|
|
|
|
|
2022-04-21 15:26:56 +00:00
|
|
|
|
switch(instruction & 0xfc0) {
|
|
|
|
|
case 0x0c0: Decode(Op::ASRm); // 4-22 (p126)
|
|
|
|
|
case 0x1c0: Decode(Op::ASLm); // 4-22 (p126)
|
|
|
|
|
case 0x2c0: Decode(Op::LSRm); // 4-113 (p217)
|
|
|
|
|
case 0x3c0: Decode(Op::LSLm); // 4-113 (p217)
|
|
|
|
|
case 0x4c0: Decode(Op::ROXRm); // 4-163 (p267)
|
|
|
|
|
case 0x5c0: Decode(Op::ROXLm); // 4-163 (p267)
|
|
|
|
|
case 0x6c0: Decode(Op::RORm); // 4-160 (p264)
|
|
|
|
|
case 0x7c0: Decode(Op::ROLm); // 4-160 (p264)
|
|
|
|
|
|
2022-10-21 19:28:29 +00:00
|
|
|
|
case 0x8c0: DecodeReq(model >= Model::M68020, Op::BFTST); // 4-51 (p155)
|
2022-10-27 16:13:13 +00:00
|
|
|
|
case 0x9c0: DecodeReq(model >= Model::M68020, Op::BFEXTU); // 4-40 (p144)
|
2022-10-21 19:28:29 +00:00
|
|
|
|
case 0xac0: DecodeReq(model >= Model::M68020, Op::BFCHG); // 4-33 (p137)
|
|
|
|
|
case 0xbc0: DecodeReq(model >= Model::M68020, Op::BFEXTS); // 4-37 (p141)
|
|
|
|
|
case 0xcc0: DecodeReq(model >= Model::M68020, Op::BFCLR); // 4-35 (p139)
|
2024-12-01 14:00:29 +00:00
|
|
|
|
case 0xdc0: DecodeReq(model >= Model::M68020, Op::BFFFO); // 4-43 (p147)*
|
2022-10-21 19:28:29 +00:00
|
|
|
|
case 0xec0: DecodeReq(model >= Model::M68020, Op::BFSET); // 4-49 (p153)
|
|
|
|
|
case 0xfc0: DecodeReq(model >= Model::M68020, Op::BFINS); // 4-46 (p150)
|
|
|
|
|
|
2024-12-01 14:00:29 +00:00
|
|
|
|
// * [though the given opcode is wrong; listed same as BFEXTU]
|
|
|
|
|
|
2022-04-21 15:26:56 +00:00
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-12 13:04:40 +00:00
|
|
|
|
switch(instruction & 0x1d8) {
|
|
|
|
|
// 4-22 (p126)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x000: Decode(Op::ASRb);
|
|
|
|
|
case 0x040: Decode(Op::ASRw);
|
|
|
|
|
case 0x080: Decode(Op::ASRl);
|
2022-04-12 13:04:40 +00:00
|
|
|
|
|
|
|
|
|
// 4-113 (p217)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x008: Decode(Op::LSRb);
|
|
|
|
|
case 0x048: Decode(Op::LSRw);
|
|
|
|
|
case 0x088: Decode(Op::LSRl);
|
2022-04-12 13:04:40 +00:00
|
|
|
|
|
|
|
|
|
// 4-163 (p267)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x010: Decode(Op::ROXRb);
|
|
|
|
|
case 0x050: Decode(Op::ROXRw);
|
|
|
|
|
case 0x090: Decode(Op::ROXRl);
|
2022-04-12 13:04:40 +00:00
|
|
|
|
|
|
|
|
|
// 4-160 (p264)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x018: Decode(Op::RORb);
|
|
|
|
|
case 0x058: Decode(Op::RORw);
|
|
|
|
|
case 0x098: Decode(Op::RORl);
|
2022-04-12 13:04:40 +00:00
|
|
|
|
|
|
|
|
|
// 4-22 (p126)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x100: Decode(Op::ASLb);
|
|
|
|
|
case 0x140: Decode(Op::ASLw);
|
|
|
|
|
case 0x180: Decode(Op::ASLl);
|
2022-04-12 13:04:40 +00:00
|
|
|
|
|
|
|
|
|
// 4-113 (p217)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x108: Decode(Op::LSLb);
|
|
|
|
|
case 0x148: Decode(Op::LSLw);
|
|
|
|
|
case 0x188: Decode(Op::LSLl);
|
2022-04-12 13:04:40 +00:00
|
|
|
|
|
|
|
|
|
// 4-163 (p267)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x110: Decode(Op::ROXLb);
|
|
|
|
|
case 0x150: Decode(Op::ROXLw);
|
|
|
|
|
case 0x190: Decode(Op::ROXLl);
|
2022-04-12 13:04:40 +00:00
|
|
|
|
|
|
|
|
|
// 4-160 (p264)
|
2022-04-16 00:33:59 +00:00
|
|
|
|
case 0x118: Decode(Op::ROLb);
|
|
|
|
|
case 0x158: Decode(Op::ROLw);
|
|
|
|
|
case 0x198: Decode(Op::ROLl);
|
2022-04-12 13:04:40 +00:00
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-12 13:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-12 12:16:29 +00:00
|
|
|
|
return Preinstruction();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-12-01 13:20:24 +00:00
|
|
|
|
constexpr Preinstruction Predecoder<model>::decodeF(const uint16_t) {
|
2022-04-12 12:16:29 +00:00
|
|
|
|
return Preinstruction();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-16 00:33:59 +00:00
|
|
|
|
#undef Decode
|
2022-10-21 19:28:29 +00:00
|
|
|
|
#undef DecodeRef
|
2022-04-12 20:17:30 +00:00
|
|
|
|
|
2022-04-11 19:00:55 +00:00
|
|
|
|
// MARK: - Main decoder.
|
|
|
|
|
|
2022-04-15 13:40:37 +00:00
|
|
|
|
template <Model model>
|
2024-10-14 01:34:01 +00:00
|
|
|
|
Preinstruction Predecoder<model>::decode(const uint16_t instruction) {
|
2022-04-11 19:00:55 +00:00
|
|
|
|
// Divide first based on line.
|
|
|
|
|
switch(instruction & 0xf000) {
|
2022-04-12 12:16:29 +00:00
|
|
|
|
case 0x0000: return decode0(instruction);
|
|
|
|
|
case 0x1000: return decode1(instruction);
|
|
|
|
|
case 0x2000: return decode2(instruction);
|
|
|
|
|
case 0x3000: return decode3(instruction);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
case 0x4000: return decode4(instruction);
|
2022-04-12 12:16:29 +00:00
|
|
|
|
case 0x5000: return decode5(instruction);
|
|
|
|
|
case 0x6000: return decode6(instruction);
|
|
|
|
|
case 0x7000: return decode7(instruction);
|
2022-04-11 20:32:57 +00:00
|
|
|
|
case 0x8000: return decode8(instruction);
|
2022-04-12 12:16:29 +00:00
|
|
|
|
case 0x9000: return decode9(instruction);
|
|
|
|
|
case 0xa000: return decodeA(instruction);
|
2022-04-12 11:49:08 +00:00
|
|
|
|
case 0xb000: return decodeB(instruction);
|
2022-04-11 19:00:55 +00:00
|
|
|
|
case 0xc000: return decodeC(instruction);
|
2022-04-12 12:16:29 +00:00
|
|
|
|
case 0xd000: return decodeD(instruction);
|
|
|
|
|
case 0xe000: return decodeE(instruction);
|
|
|
|
|
case 0xf000: return decodeF(instruction);
|
2022-04-11 19:00:55 +00:00
|
|
|
|
|
2022-04-12 18:54:11 +00:00
|
|
|
|
default: break;
|
2022-04-11 19:00:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Preinstruction();
|
|
|
|
|
}
|
2022-04-18 11:23:25 +00:00
|
|
|
|
|
|
|
|
|
template class InstructionSet::M68k::Predecoder<InstructionSet::M68k::Model::M68000>;
|
2022-04-18 18:42:31 +00:00
|
|
|
|
template class InstructionSet::M68k::Predecoder<InstructionSet::M68k::Model::M68010>;
|
|
|
|
|
template class InstructionSet::M68k::Predecoder<InstructionSet::M68k::Model::M68020>;
|
|
|
|
|
template class InstructionSet::M68k::Predecoder<InstructionSet::M68k::Model::M68030>;
|
|
|
|
|
template class InstructionSet::M68k::Predecoder<InstructionSet::M68k::Model::M68040>;
|