1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-09 17:29:36 +00:00

Introduce/extend 68k enums to cover 68020 instruction set.

This commit is contained in:
Thomas Harte 2022-10-22 15:20:30 -04:00
parent cb0e259339
commit 9a56d053f8
9 changed files with 145 additions and 57 deletions

View File

@ -154,6 +154,7 @@ template <uint8_t op> uint32_t Predecoder<model>::invalid_operands() {
constexpr auto d8PCXn = Mask< AddressingMode::ProgramCounterIndirectWithIndex8bitDisplacement >::value;
constexpr auto Imm = Mask< AddressingMode::ImmediateData >::value;
constexpr auto Quick = Mask< AddressingMode::Quick >::value;
constexpr auto Ext = Mask< AddressingMode::ExtensionWord >::value;
// A few recurring combinations; terminology is directly from
// the Programmers' Reference Manual.
@ -191,11 +192,11 @@ template <uint8_t op> uint32_t Predecoder<model>::invalid_operands() {
case ADDtoRb:
case ANDtoRb: case ANDtoRw: case ANDtoRl:
case OpT(Operation::CHK):
case OpT(Operation::CHKw):
case OpT(Operation::CMPb):
case OpT(Operation::DIVU): case OpT(Operation::DIVS):
case OpT(Operation::DIVUw): case OpT(Operation::DIVSw):
case ORtoRb: case ORtoRw: case ORtoRl:
case OpT(Operation::MULU): case OpT(Operation::MULS):
case OpT(Operation::MULUw): case OpT(Operation::MULSw):
case SUBtoRb:
return ~TwoOperandMask<
AllModesNoAn,
@ -473,6 +474,11 @@ template <uint8_t op> uint32_t Predecoder<model>::invalid_operands() {
case OpT(Operation::RESET):
return ~NoOperandMask::value;
case OpT(Operation::RTM):
return ~OneOperandMask<
An | Dn
>::value;
case OpT(Operation::UNLINK):
case OpT(Operation::MOVEtoUSP):
case OpT(Operation::MOVEfromUSP):
@ -482,13 +488,13 @@ template <uint8_t op> uint32_t Predecoder<model>::invalid_operands() {
case OpT(Operation::MOVEMtoMw): case OpT(Operation::MOVEMtoMl):
return ~TwoOperandMask<
Imm,
Ext,
Ind | PreDec | d16An | d8AnXn | XXXw | XXXl
>::value;
case OpT(Operation::MOVEMtoRw): case OpT(Operation::MOVEMtoRl):
return ~TwoOperandMask<
Imm,
Ext,
Ind | PostInc | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn
>::value;
@ -664,7 +670,7 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(ui
// Implicitly: destination is a register;
// b0b2 and b3b5: source effective address.
//
case OpT(Operation::CHK):
case OpT(Operation::CHKw):
return validated<op, validate>(
combined_mode(ea_mode, ea_register), ea_register,
AddressingMode::DataRegisterDirect, data_register);
@ -697,12 +703,23 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(ui
// b9b11: destination data register;
// b0b2 and b3b5: source effective address.
//
case OpT(Operation::DIVU): case OpT(Operation::DIVS):
case OpT(Operation::MULU): case OpT(Operation::MULS):
case OpT(Operation::DIVUw): case OpT(Operation::DIVSw):
case OpT(Operation::MULUw): case OpT(Operation::MULSw):
return validated<op, validate>(
combined_mode(ea_mode, ea_register), ea_register,
AddressingMode::DataRegisterDirect, data_register);
//
// MARK: DIVSl.
//
// b0b2 and b3b5: source effective address.
// Plus an immediate word operand
//
case OpT(Operation::DIVSl):
return validated<op, validate>(
AddressingMode::ExtensionWord, 0,
combined_mode(ea_mode, ea_register), ea_register);
//
// MARK: LEA
//
@ -823,7 +840,7 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(ui
case OpT(Operation::MOVEMtoMl): case OpT(Operation::MOVEMtoMw):
case OpT(Operation::MOVEMtoRl): case OpT(Operation::MOVEMtoRw):
return validated<op, validate>(
AddressingMode::ImmediateData, 0,
AddressingMode::ExtensionWord, 0,
combined_mode(ea_mode, ea_register), ea_register);
//
@ -943,6 +960,24 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(ui
case OpT(Operation::RTD):
return validated<op, validate>(AddressingMode::ImmediateData);
//
// MARK: RTM
//
// b0b2: 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);
}
//
// MARK: DIVl
//
//
//
// MARK: Impossible error case.
//
@ -969,6 +1004,16 @@ Preinstruction Predecoder<model>::decode0(uint16_t instruction) {
case 0xa3c: Decode(Op::EORItoCCR); // 4-104 (p208)
case 0xa7c: Decode(Op::EORItoSR); // 6-10 (p464)
// 4-68 (p172)
case 0xcfc: DecodeReq(model >= Model::M68020, Op::CAS2w);
case 0xefc: DecodeReq(model >= Model::M68020, Op::CAS2l);
default: break;
}
switch(instruction & 0xff0) {
case 0x6c0: DecodeReq(model == Model::M68020, Op::RTM); // 4-167 (p271)
default: break;
}
@ -1015,7 +1060,23 @@ Preinstruction Predecoder<model>::decode0(uint16_t instruction) {
case 0xc40: Decode(CMPIw);
case 0xc80: Decode(CMPIl);
case 0x6c0: DecodeReq(model == Model::M68020, Op::CALLM); // 4-64 (p168)
// 4-64 (p168)
case 0x6c0: DecodeReq(model == Model::M68020, Op::CALLM);
// 4-67 (p171)
case 0xac0: DecodeReq(model >= Model::M68020, Op::CASb);
case 0xcc0: DecodeReq(model >= Model::M68020, Op::CASw);
case 0xec0: DecodeReq(model >= Model::M68020, Op::CASl);
// 4-72 (p176)
case 0x0c0: DecodeReq(model >= Model::M68020, Op::CHK2b);
case 0x2c0: DecodeReq(model >= Model::M68020, Op::CHK2w);
case 0x4c0: DecodeReq(model >= Model::M68020, Op::CHK2l);
// 4-83 (p187)
case 0x00c: DecodeReq(model >= Model::M68020, Op::CMP2b);
case 0x02c: DecodeReq(model >= Model::M68020, Op::CMP2w);
case 0x04c: DecodeReq(model >= Model::M68020, Op::CMP2l);
default: break;
}
@ -1163,12 +1224,15 @@ Preinstruction Predecoder<model>::decode4(uint16_t instruction) {
// 4-108 (p212)
case 0xec0: Decode(Op::JMP);
// 4-94 (p198)
case 0xc40: Decode(Op::DIVSl);
default: break;
}
switch(instruction & 0x1c0) {
case 0x1c0: Decode(Op::LEA); // 4-110 (p214)
case 0x180: Decode(Op::CHK); // 4-69 (p173)
case 0x180: Decode(Op::CHKw); // 4-69 (p173)
default: break;
}
@ -1292,8 +1356,8 @@ Preinstruction Predecoder<model>::decode8(uint16_t instruction) {
if((instruction & 0x1f0) == 0x100) Decode(Op::SBCD);
switch(instruction & 0x1c0) {
case 0x0c0: Decode(Op::DIVU); // 4-97 (p201)
case 0x1c0: Decode(Op::DIVS); // 4-93 (p197)
case 0x0c0: Decode(Op::DIVUw); // 4-97 (p201)
case 0x1c0: Decode(Op::DIVSw); // 4-93 (p197)
// 4-150 (p254)
case 0x000: Decode(ORtoRb);
@ -1398,8 +1462,8 @@ Preinstruction Predecoder<model>::decodeC(uint16_t instruction) {
}
switch(instruction & 0x1c0) {
case 0x0c0: Decode(Op::MULU); // 4-139 (p243)
case 0x1c0: Decode(Op::MULS); // 4-136 (p240)
case 0x0c0: Decode(Op::MULUw); // 4-139 (p243)
case 0x1c0: Decode(Op::MULSw); // 4-136 (p240)
// 4-15 (p119)
case 0x000: Decode(ANDtoRb);

View File

@ -81,7 +81,7 @@ template <Model model, Operation t_operation> constexpr uint8_t operand_flags(Op
//
case Operation::CMPb: case Operation::CMPw: case Operation::CMPl:
case Operation::CMPAw: case Operation::CMPAl:
case Operation::CHK:
case Operation::CHKw:
case Operation::BTST:
case Operation::LINKw:
return FetchOp1 | FetchOp2;
@ -106,8 +106,8 @@ template <Model model, Operation t_operation> constexpr uint8_t operand_flags(Op
case Operation::ORb: case Operation::ORw: case Operation::ORl:
case Operation::ANDb: case Operation::ANDw: case Operation::ANDl:
case Operation::EORb: case Operation::EORw: case Operation::EORl:
case Operation::DIVU: case Operation::DIVS:
case Operation::MULU: case Operation::MULS:
case Operation::DIVUw: case Operation::DIVSw:
case Operation::MULUw: case Operation::MULSw:
case Operation::ASLb: case Operation::ASLw: case Operation::ASLl:
case Operation::ASRb: case Operation::ASRw: case Operation::ASRl:
case Operation::LSLb: case Operation::LSLw: case Operation::LSLl:

View File

@ -80,11 +80,11 @@ constexpr DataSize operand_size(Operation r_operation) {
case Operation::MOVEPw:
case Operation::ANDw: case Operation::EORw:
case Operation::NOTw: case Operation::ORw:
case Operation::DIVU: case Operation::DIVS:
case Operation::MULU: case Operation::MULS:
case Operation::DIVUw: case Operation::DIVSw:
case Operation::MULUw: case Operation::MULSw:
case Operation::EXTbtow:
case Operation::LINKw:
case Operation::CHK:
case Operation::CHKw:
return DataSize::Word;
case Operation::ADDl: case Operation::ADDAl:

View File

@ -742,15 +742,15 @@ template <
Multiplications.
*/
case Operation::MULU: Primitive::multiply<true>(src.w, dest.l, status, flow_controller); break;
case Operation::MULS: Primitive::multiply<false>(src.w, dest.l, status, flow_controller); break;
case Operation::MULUw: Primitive::multiply<true>(src.w, dest.l, status, flow_controller); break;
case Operation::MULSw: Primitive::multiply<false>(src.w, dest.l, status, flow_controller); break;
/*
Divisions.
*/
case Operation::DIVU: Primitive::divide<true, uint16_t, uint32_t>(src.w, dest.l, status, flow_controller); break;
case Operation::DIVS: Primitive::divide<false, int16_t, int32_t>(src.w, dest.l, status, flow_controller); break;
case Operation::DIVUw: Primitive::divide<true, uint16_t, uint32_t>(src.w, dest.l, status, flow_controller); break;
case Operation::DIVSw: Primitive::divide<false, int16_t, int32_t>(src.w, dest.l, status, flow_controller); break;
// TRAP, which is a nicer form of ILLEGAL.
case Operation::TRAP:
@ -763,7 +763,7 @@ template <
}
} break;
case Operation::CHK: {
case Operation::CHKw: {
const bool is_under = s_extend16(dest.w) < 0;
const bool is_over = s_extend16(dest.w) > s_extend16(src.w);

View File

@ -217,17 +217,17 @@ const char *_to_string(Operation operation, bool is_quick) {
case Operation::ORw: return "OR.w";
case Operation::ORl: return "OR.l";
case Operation::MULU: return "MULU";
case Operation::MULS: return "MULS";
case Operation::DIVU: return "DIVU";
case Operation::DIVS: return "DIVS";
case Operation::MULUw: return "MULU";
case Operation::MULSw: return "MULS";
case Operation::DIVUw: return "DIVU";
case Operation::DIVSw: return "DIVS";
case Operation::RTE: return "RTE";
case Operation::RTR: return "RTR";
case Operation::TRAP: return "TRAP";
case Operation::TRAPV: return "TRAPV";
case Operation::CHK: return "CHK";
case Operation::CHKw: return "CHK";
case Operation::EXG: return "EXG";
case Operation::SWAP: return "SWAP";

View File

@ -61,8 +61,8 @@ enum class Operation: uint8_t {
DBcc,
Scc,
Bccb, Bccw, Bccl,
BSRb, BSRw, BSRl,
Bccb, Bccw,
BSRb, BSRw,
CLRb, CLRw, CLRl,
NEGXb, NEGXw, NEGXl,
@ -87,13 +87,13 @@ enum class Operation: uint8_t {
NOTb, NOTw, NOTl,
ORb, ORw, ORl,
MULU, MULS,
DIVU, DIVS,
MULUw, MULSw,
DIVUw, DIVSw,
RTE, RTR,
TRAP, TRAPV,
CHK,
CHKw,
EXG, SWAP,
@ -108,23 +108,30 @@ enum class Operation: uint8_t {
//
// 68020 additions.
//
BKPT,
BKPT, TRAPcc,
CALLM, RTD, RTM,
BFCHG, BFCLR,
BFEXTS, BFEXTU,
BFFFO, BFINS,
BFSET, BFTST,
CALLM, RTD, RTM,
PACK, UNPK,
CAS, CAS2,
CHK2, CMP2,
CASb, CASw, CASl,
CAS2w, CAS2l,
CHK2b, CHK2w, CHK2l,
CMP2b, CMP2w, CMP2l,
DIVSl, DIVUl,
MULSl, MULUl,
Bccl, BSRl,
LINKl, CHKl,
DIVSL,
EXTbtol,
PACK, UNPK,
TRAPcc,
cpBcc, cpDBcc, cpGEN,
cpScc, cpTRAPcc, cpRESTORE,
@ -285,6 +292,10 @@ enum class AddressingMode: uint8_t {
/// #
ImmediateData = 0b01'100,
/// An additional word of data. Differs from ImmediateData by being
/// a fixed size, rather than the @c operand_size of the operation.
ExtensionWord = 0b01'111,
/// .q; value is embedded in the opcode.
Quick = 0b01'110,
};

View File

@ -438,8 +438,8 @@ struct TestProcessor: public CPU::MC68000Mk2::BusHandler {
// For DIVU and DIVS, for now, test only the well-defined flags.
if(
instruction.operation != InstructionSet::M68k::Operation::DIVS &&
instruction.operation != InstructionSet::M68k::Operation::DIVU
instruction.operation != InstructionSet::M68k::Operation::DIVSw &&
instruction.operation != InstructionSet::M68k::Operation::DIVUw
) {
[_failures addObject:name];
} else {

View File

@ -540,17 +540,17 @@ void print_transactions(FILE *target, const std::vector<Transaction> &transactio
InstructionSet::M68k::Operation::NOTw, // Old implementation omits an idle cycle before -(An)
InstructionSet::M68k::Operation::TRAP, // Old implementation relocates the idle state near the end to the beginning.
InstructionSet::M68k::Operation::TRAPV, // Old implementation relocates the idle state near the end to the beginning.
InstructionSet::M68k::Operation::CHK, // Old implementation pauses four cycles too long.
InstructionSet::M68k::Operation::CHKw, // Old implementation pauses four cycles too long.
InstructionSet::M68k::Operation::TAS, // Old implementation just doesn't match published cycle counts.
//
// Operations with timing discrepancies between the two 68000 implementations
// that I think are _more_ accurate now, but possibly still need work:
//
InstructionSet::M68k::Operation::MULU,
InstructionSet::M68k::Operation::MULS,
InstructionSet::M68k::Operation::DIVU,
InstructionSet::M68k::Operation::DIVS,
InstructionSet::M68k::Operation::MULUw,
InstructionSet::M68k::Operation::MULSw,
InstructionSet::M68k::Operation::DIVUw,
InstructionSet::M68k::Operation::DIVSw,
};
int testsRun = 0;

View File

@ -826,7 +826,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
MoveToStateSpecific(TwoOp_Predec_bw);
}
StdCASE(CHK, perform_state_ = CHK);
StdCASE(CHKw, perform_state_ = CHK);
Duplicate(SUBb, ADDb) StdCASE(ADDb, perform_state_ = Perform_np)
Duplicate(SUBw, ADDw) StdCASE(ADDw, perform_state_ = Perform_np)
@ -1002,10 +1002,10 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
StdCASE(TSTw, perform_state_ = Perform_np);
StdCASE(TSTl, perform_state_ = Perform_np);
StdCASE(DIVU, perform_state_ = DIVU_DIVS);
StdCASE(DIVS, perform_state_ = DIVU_DIVS);
StdCASE(MULU, perform_state_ = Perform_idle_dyamic_Dn);
StdCASE(MULS, perform_state_ = Perform_idle_dyamic_Dn);
StdCASE(DIVUw, perform_state_ = DIVU_DIVS);
StdCASE(DIVSw, perform_state_ = DIVU_DIVS);
StdCASE(MULUw, perform_state_ = Perform_idle_dyamic_Dn);
StdCASE(MULSw, perform_state_ = Perform_idle_dyamic_Dn);
StdCASE(LEA, {
post_ea_state_ = LEA;
@ -1833,6 +1833,19 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
Prefetch(); // np
MoveToNextOperand(FetchOperand_l);
//
// ExtensionWord; always the same size.
//
BeginStateMode(FetchOperand_bw, ExtensionWord):
operand_[next_operand_].w = prefetch_.w;
Prefetch(); // np
MoveToNextOperand(FetchOperand_bw);
BeginStateMode(FetchOperand_l, ExtensionWord):
operand_[next_operand_].w = prefetch_.w;
Prefetch(); // np
MoveToNextOperand(FetchOperand_l);
#undef MoveToNextOperand
// MARK: - Store.
@ -2033,7 +2046,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
//
BeginState(CHK):
Prefetch(); // np
PerformSpecific(CHK);
PerformSpecific(CHKw);
// Proper next state will have been set by the flow controller
// call-in; just allow dispatch to whatever it was.