mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-22 12:33:29 +00:00
Accept that a uint8_t isn't always going to be large enough; split decoding by minimum processor.
This commit is contained in:
parent
8c670d2105
commit
38c531fd5a
@ -71,7 +71,7 @@ uint32_t operand_mask(AddressingMode mode1, AddressingMode mode2) {
|
||||
/// immediate operand.
|
||||
template <Model model>
|
||||
constexpr Operation Predecoder<model>::operation(OpT op) {
|
||||
if(op <= OpT(Operation::Max)) {
|
||||
if(op <= OpMax) {
|
||||
return Operation(op);
|
||||
}
|
||||
|
||||
@ -140,7 +140,7 @@ constexpr Operation Predecoder<model>::operation(OpT op) {
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
template <uint8_t op> uint32_t Predecoder<model>::invalid_operands() {
|
||||
template <typename Predecoder<model>::OpT op> uint32_t Predecoder<model>::invalid_operands() {
|
||||
constexpr auto Dn = Mask< AddressingMode::DataRegisterDirect >::value;
|
||||
constexpr auto An = Mask< AddressingMode::AddressRegisterDirect >::value;
|
||||
constexpr auto Ind = Mask< AddressingMode::AddressRegisterIndirect >::value;
|
||||
@ -174,12 +174,15 @@ template <uint8_t op> uint32_t Predecoder<model>::invalid_operands() {
|
||||
//
|
||||
// Control [flow] addressing modes.
|
||||
//
|
||||
static constexpr auto ControlAddressingModes = Ind | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn;
|
||||
static constexpr auto ControlAddressingModes = Ind | d16An | d8AnXn | XXXw | XXXl | d16PC | d8PCXn;
|
||||
|
||||
//
|
||||
// An invalid response, used as the default case.
|
||||
//
|
||||
static constexpr auto InvalidOperands = uint32_t(~0);
|
||||
|
||||
switch(op) {
|
||||
// By default, disallow all operands (including 'None'). This should catch any
|
||||
// opcodes that are unmapped below.
|
||||
default: return uint32_t(~0);
|
||||
default: break;
|
||||
|
||||
case OpT(Operation::ABCD):
|
||||
case OpT(Operation::ADDXb): case OpT(Operation::ADDXw): case OpT(Operation::ADDXl):
|
||||
@ -280,8 +283,7 @@ template <uint8_t op> uint32_t Predecoder<model>::invalid_operands() {
|
||||
>::value;
|
||||
|
||||
case OpT(Operation::ANDItoCCR): case OpT(Operation::ANDItoSR):
|
||||
case OpT(Operation::Bccw): case OpT(Operation::Bccl):
|
||||
case OpT(Operation::BSRl): case OpT(Operation::BSRw):
|
||||
case OpT(Operation::Bccw): case OpT(Operation::BSRw):
|
||||
case OpT(Operation::EORItoCCR): case OpT(Operation::EORItoSR):
|
||||
case OpT(Operation::ORItoCCR): case OpT(Operation::ORItoSR):
|
||||
case OpT(Operation::STOP):
|
||||
@ -317,7 +319,6 @@ template <uint8_t op> uint32_t Predecoder<model>::invalid_operands() {
|
||||
case OpT(Operation::Bccb):
|
||||
case OpT(Operation::BSRb):
|
||||
case OpT(Operation::TRAP):
|
||||
case OpT(Operation::BKPT):
|
||||
return ~OneOperandMask<
|
||||
Quick
|
||||
>::value;
|
||||
@ -337,25 +338,6 @@ template <uint8_t op> uint32_t Predecoder<model>::invalid_operands() {
|
||||
AllModesNoAn
|
||||
>::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;
|
||||
|
||||
case OpT(Operation::PACK):
|
||||
return ~OneOperandMask<
|
||||
Imm
|
||||
>::value;
|
||||
|
||||
case CMPIb: case CMPIl: case CMPIw:
|
||||
if constexpr (model == Model::M68000) {
|
||||
return ~TwoOperandMask<
|
||||
@ -442,16 +424,6 @@ template <uint8_t op> uint32_t Predecoder<model>::invalid_operands() {
|
||||
Dn
|
||||
>::value;
|
||||
|
||||
case OpT(Operation::RTD):
|
||||
return ~OneOperandMask<
|
||||
Imm
|
||||
>::value;
|
||||
|
||||
case OpT(Operation::CALLM):
|
||||
return ~OneOperandMask<
|
||||
ControlAddressingModes
|
||||
>::value;
|
||||
|
||||
case OpT(Operation::JMP):
|
||||
case OpT(Operation::JSR):
|
||||
case OpT(Operation::PEA):
|
||||
@ -479,11 +451,6 @@ 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):
|
||||
@ -515,11 +482,78 @@ template <uint8_t op> uint32_t Predecoder<model>::invalid_operands() {
|
||||
d16An
|
||||
>::value;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 68010 additions.
|
||||
//
|
||||
if constexpr (model <= Model::M68010) {
|
||||
return InvalidOperands;
|
||||
}
|
||||
switch(op) {
|
||||
default: break;
|
||||
|
||||
case OpT(Operation::BKPT):
|
||||
return ~OneOperandMask<
|
||||
Quick
|
||||
>::value;
|
||||
|
||||
case OpT(Operation::RTD):
|
||||
return ~OneOperandMask<
|
||||
Imm
|
||||
>::value;
|
||||
}
|
||||
|
||||
//
|
||||
// 68020 additions.
|
||||
//
|
||||
if constexpr (model <= Model::M68020) {
|
||||
return InvalidOperands;
|
||||
}
|
||||
switch(op) {
|
||||
default: break;
|
||||
|
||||
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;
|
||||
|
||||
case OpT(Operation::PACK):
|
||||
return ~OneOperandMask<
|
||||
Imm
|
||||
>::value;
|
||||
}
|
||||
|
||||
return InvalidOperands;
|
||||
}
|
||||
|
||||
/// Provides a post-decoding validation step — primarily ensures that the prima facie addressing modes are supported by the operation.
|
||||
template <Model model>
|
||||
template <uint8_t 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 op2_mode, int op2_reg,
|
||||
Condition condition
|
||||
@ -554,7 +588,7 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::validated
|
||||
/// Decodes the fields within an instruction and constructs a `Preinstruction`, given that the operation has already been
|
||||
/// decoded. Optionally applies validation
|
||||
template <Model model>
|
||||
template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(uint16_t instruction) {
|
||||
template <typename Predecoder<model>::OpT op, bool validate> Preinstruction Predecoder<model>::decode(uint16_t instruction) {
|
||||
// Fields used pervasively below.
|
||||
//
|
||||
// Underlying assumption: the compiler will discard whatever of these
|
||||
@ -564,7 +598,11 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(ui
|
||||
const auto opmode = (instruction >> 6) & 7;
|
||||
const auto data_register = (instruction >> 9) & 7;
|
||||
|
||||
//
|
||||
// Operations common to all processors.
|
||||
//
|
||||
switch(op) {
|
||||
default: break;
|
||||
|
||||
//
|
||||
// MARK: ABCD, SBCD, ADDX.
|
||||
@ -648,24 +686,24 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(ui
|
||||
combined_mode(ea_mode, ea_register), ea_register);
|
||||
|
||||
//
|
||||
// MARK: STOP, ANDItoCCR, ANDItoSR, EORItoCCR, EORItoSR, ORItoCCR, ORItoSR, BSRl, BSRw
|
||||
// MARK: STOP, ANDItoCCR, ANDItoSR, EORItoCCR, EORItoSR, ORItoCCR, ORItoSR, BSRw
|
||||
//
|
||||
// Operand is an immedate; destination/source (if any) is implied by the operation,
|
||||
// e.g. ORItoSR has a destination of SR.
|
||||
//
|
||||
case OpT(Operation::STOP):
|
||||
case OpT(Operation::BSRl): case OpT(Operation::BSRw):
|
||||
case OpT(Operation::BSRw):
|
||||
case OpT(Operation::ORItoSR): case OpT(Operation::ORItoCCR):
|
||||
case OpT(Operation::ANDItoSR): case OpT(Operation::ANDItoCCR):
|
||||
case OpT(Operation::EORItoSR): case OpT(Operation::EORItoCCR):
|
||||
return validated<op, validate>(AddressingMode::ImmediateData);
|
||||
|
||||
//
|
||||
// MARK: Bccl, Bccw
|
||||
// MARK: Bccw
|
||||
//
|
||||
// Operand is an immedate; b8–b11 are a condition code.
|
||||
//
|
||||
case OpT(Operation::Bccl): case OpT(Operation::Bccw):
|
||||
case OpT(Operation::Bccw):
|
||||
return validated<op, validate>(
|
||||
AddressingMode::ImmediateData, 0,
|
||||
AddressingMode::None, 0,
|
||||
@ -683,7 +721,7 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(ui
|
||||
AddressingMode::DataRegisterDirect, data_register);
|
||||
|
||||
//
|
||||
// MARK: EXG.
|
||||
// MARK: EXG
|
||||
//
|
||||
// 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);
|
||||
@ -716,17 +754,6 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(ui
|
||||
combined_mode(ea_mode, ea_register), ea_register,
|
||||
AddressingMode::DataRegisterDirect, data_register);
|
||||
|
||||
//
|
||||
// MARK: DIVSl.
|
||||
//
|
||||
// b0–b2 and b3–b5: 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
|
||||
//
|
||||
@ -851,11 +878,10 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(ui
|
||||
combined_mode(ea_mode, ea_register), ea_register);
|
||||
|
||||
//
|
||||
// MARK: TRAP, BCCb, BSRb, BKPT
|
||||
// MARK: TRAP, BCCb, BSRb
|
||||
//
|
||||
// No further operands decoded, but one is somewhere in the opcode.
|
||||
//
|
||||
case OpT(Operation::BKPT):
|
||||
case OpT(Operation::TRAP):
|
||||
case OpT(Operation::BSRb):
|
||||
return validated<op, validate>(AddressingMode::Quick);
|
||||
@ -936,6 +962,70 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(ui
|
||||
return validated<op, validate>(
|
||||
AddressingMode::AddressRegisterIndirectWithPostincrement, ea_register,
|
||||
AddressingMode::AddressRegisterIndirectWithPostincrement, data_register);
|
||||
}
|
||||
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
|
||||
//
|
||||
// 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
|
||||
//
|
||||
case OpT(Operation::DIVSl):
|
||||
return validated<op, validate>(
|
||||
AddressingMode::ExtensionWord, 0,
|
||||
combined_mode(ea_mode, ea_register), ea_register);
|
||||
|
||||
//
|
||||
// MARK: BFCHG, BFTST, BFFFO, BFEXTU, BFEXTS, BFCLR, BFSET, BFINS
|
||||
@ -961,12 +1051,6 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(ui
|
||||
AddressingMode::ImmediateData, 0,
|
||||
combined_mode(ea_mode, ea_register), ea_register);
|
||||
|
||||
//
|
||||
// MARK: RTD
|
||||
//
|
||||
case OpT(Operation::RTD):
|
||||
return validated<op, validate>(AddressingMode::ImmediateData);
|
||||
|
||||
//
|
||||
// MARK: RTM
|
||||
//
|
||||
@ -996,14 +1080,11 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(ui
|
||||
// MARK: DIVl
|
||||
//
|
||||
//
|
||||
|
||||
//
|
||||
// MARK: Impossible error case.
|
||||
//
|
||||
default:
|
||||
// Should be unreachable.
|
||||
assert(false);
|
||||
// TODO.
|
||||
}
|
||||
|
||||
// Should be unreachable.
|
||||
assert(false);
|
||||
}
|
||||
|
||||
// MARK: - Page decoders.
|
||||
@ -1151,7 +1232,6 @@ Preinstruction Predecoder<model>::decode3(uint16_t instruction) {
|
||||
case 0x040: Decode(Op::MOVEAw);
|
||||
default: Decode(Op::MOVEw);
|
||||
}
|
||||
// Decode(Op::MOVEw);
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
|
@ -50,7 +50,30 @@ template <Model model> class Predecoder {
|
||||
Preinstruction decodeE(uint16_t instruction);
|
||||
Preinstruction decodeF(uint16_t instruction);
|
||||
|
||||
using OpT = uint8_t;
|
||||
template <Model> struct OperationProperties {};
|
||||
template <> struct OperationProperties<Model::M68000> {
|
||||
using OpT = uint8_t;
|
||||
static constexpr OpT OpMax = OpT(Operation::Max68000);
|
||||
};
|
||||
template <> struct OperationProperties<Model::M68010> {
|
||||
using OpT = uint8_t;
|
||||
static constexpr OpT OpMax = OpT(Operation::Max68010);
|
||||
};
|
||||
template <> struct OperationProperties<Model::M68020> {
|
||||
using OpT = uint16_t;
|
||||
static constexpr OpT OpMax = OpT(Operation::Max68020);
|
||||
};
|
||||
template <> struct OperationProperties<Model::M68030> {
|
||||
using OpT = uint16_t;
|
||||
static constexpr OpT OpMax = OpT(Operation::Max68030);
|
||||
};
|
||||
template <> struct OperationProperties<Model::M68040> {
|
||||
using OpT = uint16_t;
|
||||
static constexpr OpT OpMax = OpT(Operation::Max68040);
|
||||
};
|
||||
|
||||
using OpT = typename OperationProperties<model>::OpT;
|
||||
static constexpr OpT OpMax = OperationProperties<model>::OpMax;
|
||||
|
||||
// Specific instruction decoders.
|
||||
template <OpT operation, bool validate = true> Preinstruction decode(uint16_t instruction);
|
||||
@ -59,14 +82,14 @@ template <Model model> class Predecoder {
|
||||
AddressingMode op2_mode = AddressingMode::None, int op2_reg = 0,
|
||||
Condition condition = Condition::True
|
||||
);
|
||||
template <uint8_t op> uint32_t invalid_operands();
|
||||
template <OpT operation> uint32_t invalid_operands();
|
||||
|
||||
// Extended operation list; collapses into a single byte enough information to
|
||||
// know both the type of operation and how to decode the operands. Most of the
|
||||
// time that's knowable from the Operation alone, hence the rather awkward
|
||||
// extension of @c Operation.
|
||||
enum ExtendedOperation: OpT {
|
||||
MOVEPtoRl = uint8_t(Operation::Max) + 1, MOVEPtoRw,
|
||||
MOVEPtoRl = OperationProperties<model>::OpMax + 1, MOVEPtoRw,
|
||||
MOVEPtoMl, MOVEPtoMw,
|
||||
|
||||
MOVEQ,
|
||||
@ -87,8 +110,6 @@ template <Model model> class Predecoder {
|
||||
|
||||
CMPMb, CMPMw, CMPMl,
|
||||
|
||||
MOVEq,
|
||||
|
||||
ADDtoMb, ADDtoMw, ADDtoMl,
|
||||
ADDtoRb, ADDtoRw, ADDtoRl,
|
||||
|
||||
|
@ -105,12 +105,19 @@ enum class Operation: uint8_t {
|
||||
|
||||
STOP, RESET,
|
||||
|
||||
//
|
||||
// 68010 additions.
|
||||
//
|
||||
|
||||
BKPT, RTD,
|
||||
|
||||
//
|
||||
// 68020 additions.
|
||||
//
|
||||
BKPT, TRAPcc,
|
||||
|
||||
CALLM, RTD, RTM,
|
||||
TRAPcc,
|
||||
|
||||
CALLM, RTM,
|
||||
|
||||
BFCHG, BFCLR,
|
||||
BFEXTS, BFEXTU,
|
||||
@ -140,10 +147,31 @@ enum class Operation: uint8_t {
|
||||
MOVEfromCCR,
|
||||
MOVEC, MOVES,
|
||||
|
||||
//
|
||||
// 68030 additions.
|
||||
//
|
||||
|
||||
PFLUSH, PFLUSHA,
|
||||
PLOADR, PLOADW,
|
||||
PMOVE, PMOVEFD,
|
||||
PTESTR, PTESTW,
|
||||
|
||||
//
|
||||
// 68040 additions.
|
||||
//
|
||||
|
||||
// TODO: the big addition of the 68040 is incorporation of the FPU; should I make decoding of those instructions
|
||||
// dependent upon a 68040 being selected, or should I offer a separate decoder in order to support systems with
|
||||
// a coprocessor?
|
||||
|
||||
//
|
||||
// Introspection.
|
||||
//
|
||||
Max = MOVES
|
||||
Max68000 = RESET,
|
||||
Max68010 = RTD,
|
||||
Max68020 = MOVES,
|
||||
Max68030 = PTESTW,
|
||||
Max68040 = PTESTW,
|
||||
};
|
||||
|
||||
const char *to_string(Operation op);
|
||||
@ -365,15 +393,26 @@ class Preinstruction {
|
||||
return operands_[index] & 0xf;
|
||||
}
|
||||
|
||||
/// @returns @c true if this instruction requires supervisor privileges; @c false otherwise.
|
||||
bool requires_supervisor() const {
|
||||
return flags_ & Flags::IsSupervisor;
|
||||
}
|
||||
bool requires_extension_word() const {
|
||||
return flags_ & Flags::RequiresExtensionWord;
|
||||
/// @returns @c true if this instruction will require further fetching than can be encoded in a
|
||||
/// @c Preinstruction. In practice this means it is one of a very small quantity of 68020+
|
||||
/// instructions; those that can rationalise extension words into one of the two operands will
|
||||
/// do so. Use the free function @c extension_words(instruction.operation) to
|
||||
/// look up the number of additional words required.
|
||||
///
|
||||
/// (specifically affected, at least: PACK, UNPK, CAS, CAS2)
|
||||
bool requires_further_extension() const {
|
||||
return flags_ & Flags::RequiresFurtherExtension;
|
||||
}
|
||||
/// @returns The @c DataSize used for operands of this instruction, i.e. byte, word or longword.
|
||||
DataSize operand_size() const {
|
||||
return DataSize((flags_ & Flags::SizeMask) >> Flags::SizeShift);
|
||||
}
|
||||
/// @returns The condition code evaluated by this instruction if applicable. If this instruction is not
|
||||
/// conditional, the result is undefined.
|
||||
Condition condition() const {
|
||||
return Condition((flags_ & Flags::ConditionMask) >> Flags::ConditionShift);
|
||||
}
|
||||
@ -390,7 +429,7 @@ class Preinstruction {
|
||||
AddressingMode op1_mode, int op1_reg,
|
||||
AddressingMode op2_mode, int op2_reg,
|
||||
bool is_supervisor,
|
||||
bool requires_extension_word,
|
||||
bool requires_further_extension,
|
||||
DataSize size,
|
||||
Condition condition) : operation(operation)
|
||||
{
|
||||
@ -398,17 +437,17 @@ class Preinstruction {
|
||||
operands_[1] = uint8_t((uint8_t(op2_mode) << 3) | op2_reg);
|
||||
flags_ = uint8_t(
|
||||
(is_supervisor ? Flags::IsSupervisor : 0x00) |
|
||||
(requires_extension_word ? Flags::RequiresExtensionWord : 0x00) |
|
||||
(requires_further_extension ? Flags::RequiresFurtherExtension : 0x00) |
|
||||
(int(condition) << Flags::ConditionShift) |
|
||||
(int(size) << Flags::SizeShift)
|
||||
);
|
||||
}
|
||||
|
||||
struct Flags {
|
||||
static constexpr uint8_t IsSupervisor = 0b1000'0000;
|
||||
static constexpr uint8_t RequiresExtensionWord = 0b0100'0000;
|
||||
static constexpr uint8_t ConditionMask = 0b0011'1100;
|
||||
static constexpr uint8_t SizeMask = 0b0000'0011;
|
||||
static constexpr uint8_t IsSupervisor = 0b1000'0000;
|
||||
static constexpr uint8_t RequiresFurtherExtension = 0b0100'0000;
|
||||
static constexpr uint8_t ConditionMask = 0b0011'1100;
|
||||
static constexpr uint8_t SizeMask = 0b0000'0011;
|
||||
|
||||
static constexpr int ConditionShift = 2;
|
||||
static constexpr int SizeShift = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user