mirror of
https://github.com/TomHarte/CLK.git
synced 2025-08-09 05:25:01 +00:00
Support up to 15 extension words on a Preinstruction; use that to describe PACK/UNPK.
TODO: reconcile when to use that field versus the ExtensionWord operand. Probably only when operands are full?
This commit is contained in:
@@ -564,9 +564,10 @@ template <typename Predecoder<model>::OpT op> uint32_t Predecoder<model>::invali
|
|||||||
Dn | Ind | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn
|
Dn | Ind | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn
|
||||||
>::value;
|
>::value;
|
||||||
|
|
||||||
case OpT(Operation::PACK):
|
case OpT(Operation::PACK): case OpT(Operation::UNPK):
|
||||||
return ~OneOperandMask<
|
return ~TwoOperandMask<
|
||||||
Imm
|
Dn | PreDec,
|
||||||
|
Dn | PreDec
|
||||||
>::value;
|
>::value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,7 +579,8 @@ template <Model model>
|
|||||||
template <typename Predecoder<model>::OpT op, bool validate> Preinstruction Predecoder<model>::validated(
|
template <typename Predecoder<model>::OpT op, bool validate> Preinstruction Predecoder<model>::validated(
|
||||||
AddressingMode op1_mode, int op1_reg,
|
AddressingMode op1_mode, int op1_reg,
|
||||||
AddressingMode op2_mode, int op2_reg,
|
AddressingMode op2_mode, int op2_reg,
|
||||||
Condition condition
|
Condition condition,
|
||||||
|
int additional_extension_words
|
||||||
) {
|
) {
|
||||||
constexpr auto operation = Predecoder<model>::operation(op);
|
constexpr auto operation = Predecoder<model>::operation(op);
|
||||||
|
|
||||||
@@ -588,7 +590,7 @@ template <typename Predecoder<model>::OpT op, bool validate> Preinstruction Pred
|
|||||||
op1_mode, op1_reg,
|
op1_mode, op1_reg,
|
||||||
op2_mode, op2_reg,
|
op2_mode, op2_reg,
|
||||||
requires_supervisor<model>(operation),
|
requires_supervisor<model>(operation),
|
||||||
requires_extension_word(operation),
|
additional_extension_words,
|
||||||
operand_size(operation),
|
operand_size(operation),
|
||||||
condition);
|
condition);
|
||||||
}
|
}
|
||||||
@@ -602,7 +604,7 @@ template <typename Predecoder<model>::OpT op, bool validate> Preinstruction Pred
|
|||||||
op1_mode, op1_reg,
|
op1_mode, op1_reg,
|
||||||
op2_mode, op2_reg,
|
op2_mode, op2_reg,
|
||||||
requires_supervisor<model>(operation),
|
requires_supervisor<model>(operation),
|
||||||
requires_extension_word(operation),
|
additional_extension_words,
|
||||||
operand_size(operation),
|
operand_size(operation),
|
||||||
condition);
|
condition);
|
||||||
}
|
}
|
||||||
@@ -1135,17 +1137,23 @@ template <typename Predecoder<model>::OpT op, bool validate> Preinstruction Pred
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// MARK: PACK
|
// MARK: PACK, UNPK
|
||||||
//
|
//
|
||||||
// b0–b2: a register number;
|
// b9–b11: Rx (destination)
|
||||||
// b3: address/data register selection — if address registers, then this is predec;
|
// b0–b2: Ry (source)
|
||||||
// b9–b11: an additional register number.
|
// b3: 1 => operation is memory-to-memory; 0 => register-to-register.
|
||||||
// This instruction is also followed by a 16-bit adjustment extension.
|
// This instruction is also followed by a 16-bit adjustment extension.
|
||||||
//
|
//
|
||||||
case OpT(Operation::PACK):
|
case OpT(Operation::PACK):
|
||||||
// TODO; need to square the wheel on a prima-facie three operands.
|
case OpT(Operation::UNPK): {
|
||||||
return Preinstruction();
|
const auto addressing_mode = (instruction & 8) ?
|
||||||
|
AddressingMode::AddressRegisterIndirectWithPredecrement : AddressingMode::DataRegisterDirect;
|
||||||
|
|
||||||
|
return validated<op, validate>(
|
||||||
|
addressing_mode, ea_register,
|
||||||
|
addressing_mode, data_register,
|
||||||
|
Condition::True, 1);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// MARK: DIVl
|
// MARK: DIVl
|
||||||
@@ -1547,6 +1555,7 @@ Preinstruction Predecoder<model>::decode8(uint16_t instruction) {
|
|||||||
switch(instruction & 0x1f0) {
|
switch(instruction & 0x1f0) {
|
||||||
case 0x100: Decode(Op::SBCD); // 4-171 (p275)
|
case 0x100: Decode(Op::SBCD); // 4-171 (p275)
|
||||||
case 0x140: DecodeReq(model >= Model::M68020, Op::PACK); // 4-157 (p261)
|
case 0x140: DecodeReq(model >= Model::M68020, Op::PACK); // 4-157 (p261)
|
||||||
|
case 0x180: DecodeReq(model >= Model::M68020, Op::UNPK); // 4-196 (p300)
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
@@ -66,7 +66,8 @@ template <Model model> class Predecoder {
|
|||||||
template <OpT operation, bool validate> Preinstruction validated(
|
template <OpT operation, bool validate> Preinstruction validated(
|
||||||
AddressingMode op1_mode = AddressingMode::None, int op1_reg = 0,
|
AddressingMode op1_mode = AddressingMode::None, int op1_reg = 0,
|
||||||
AddressingMode op2_mode = AddressingMode::None, int op2_reg = 0,
|
AddressingMode op2_mode = AddressingMode::None, int op2_reg = 0,
|
||||||
Condition condition = Condition::True
|
Condition condition = Condition::True,
|
||||||
|
int further_extension_words = 0
|
||||||
);
|
);
|
||||||
template <OpT operation> uint32_t invalid_operands();
|
template <OpT operation> uint32_t invalid_operands();
|
||||||
|
|
||||||
|
@@ -294,6 +294,9 @@ std::string Preinstruction::to_string(int opcode) const {
|
|||||||
if(!operand1.empty()) result += std::string(" ") + operand1;
|
if(!operand1.empty()) result += std::string(" ") + operand1;
|
||||||
if(!operand2.empty()) result += std::string(", ") + operand2;
|
if(!operand2.empty()) result += std::string(", ") + operand2;
|
||||||
|
|
||||||
|
const int extension_words = additional_extension_words();
|
||||||
|
if(extension_words) result += std::string(" [+") + std::to_string(extension_words) + "]";
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -215,16 +215,6 @@ constexpr bool requires_supervisor(Operation op) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline constexpr bool requires_extension_word(Operation op) {
|
|
||||||
switch(op) {
|
|
||||||
case Operation::PACK:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class DataSize {
|
enum class DataSize {
|
||||||
Byte = 0,
|
Byte = 0,
|
||||||
Word = 1,
|
Word = 1,
|
||||||
@@ -426,6 +416,10 @@ class Preinstruction {
|
|||||||
bool requires_further_extension() const {
|
bool requires_further_extension() const {
|
||||||
return flags_ & Flags::RequiresFurtherExtension;
|
return flags_ & Flags::RequiresFurtherExtension;
|
||||||
}
|
}
|
||||||
|
/// @returns The number of additional extension words required, beyond those encoded as operands.
|
||||||
|
int additional_extension_words() const {
|
||||||
|
return flags_ & Flags::RequiresFurtherExtension ? (flags_ & Flags::ConditionMask) >> Flags::ConditionShift : 0;
|
||||||
|
}
|
||||||
/// @returns The @c DataSize used for operands of this instruction, i.e. byte, word or longword.
|
/// @returns The @c DataSize used for operands of this instruction, i.e. byte, word or longword.
|
||||||
DataSize operand_size() const {
|
DataSize operand_size() const {
|
||||||
return DataSize((flags_ & Flags::SizeMask) >> Flags::SizeShift);
|
return DataSize((flags_ & Flags::SizeMask) >> Flags::SizeShift);
|
||||||
@@ -448,7 +442,7 @@ class Preinstruction {
|
|||||||
AddressingMode op1_mode, int op1_reg,
|
AddressingMode op1_mode, int op1_reg,
|
||||||
AddressingMode op2_mode, int op2_reg,
|
AddressingMode op2_mode, int op2_reg,
|
||||||
bool is_supervisor,
|
bool is_supervisor,
|
||||||
bool requires_further_extension,
|
int extension_words,
|
||||||
DataSize size,
|
DataSize size,
|
||||||
Condition condition) : operation(operation)
|
Condition condition) : operation(operation)
|
||||||
{
|
{
|
||||||
@@ -456,8 +450,9 @@ class Preinstruction {
|
|||||||
operands_[1] = uint8_t((uint8_t(op2_mode) << 3) | op2_reg);
|
operands_[1] = uint8_t((uint8_t(op2_mode) << 3) | op2_reg);
|
||||||
flags_ = uint8_t(
|
flags_ = uint8_t(
|
||||||
(is_supervisor ? Flags::IsSupervisor : 0x00) |
|
(is_supervisor ? Flags::IsSupervisor : 0x00) |
|
||||||
(requires_further_extension ? Flags::RequiresFurtherExtension : 0x00) |
|
(extension_words ? Flags::RequiresFurtherExtension : 0x00) |
|
||||||
(int(condition) << Flags::ConditionShift) |
|
(int(condition) << Flags::ConditionShift) |
|
||||||
|
(extension_words << Flags::ConditionShift) |
|
||||||
(int(size) << Flags::SizeShift)
|
(int(size) << Flags::SizeShift)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -468,8 +463,10 @@ class Preinstruction {
|
|||||||
static constexpr uint8_t ConditionMask = 0b0011'1100;
|
static constexpr uint8_t ConditionMask = 0b0011'1100;
|
||||||
static constexpr uint8_t SizeMask = 0b0000'0011;
|
static constexpr uint8_t SizeMask = 0b0000'0011;
|
||||||
|
|
||||||
static constexpr int ConditionShift = 2;
|
static constexpr int IsSupervisorShift = 7;
|
||||||
static constexpr int SizeShift = 0;
|
static constexpr int RequiresFurtherExtensionShift = 6;
|
||||||
|
static constexpr int ConditionShift = 2;
|
||||||
|
static constexpr int SizeShift = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Preinstruction() {}
|
Preinstruction() {}
|
||||||
|
Reference in New Issue
Block a user