mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-15 05:31:30 +00:00
Const
as many arguments as possible.
This commit is contained in:
parent
9c550a8154
commit
a7d2b0f63b
@ -27,7 +27,7 @@ constexpr AddressingMode extended_modes[] = {
|
||||
|
||||
/// @returns The @c AddressingMode given the specified mode and reg, subject to potential
|
||||
/// aliasing on the '020+ as described above the @c AddressingMode enum.
|
||||
constexpr AddressingMode combined_mode(int mode, int reg) {
|
||||
constexpr AddressingMode combined_mode(const int mode, const int reg) {
|
||||
assert(mode >= 0 && mode < 8);
|
||||
assert(reg >= 0 && reg < 8);
|
||||
|
||||
@ -55,7 +55,7 @@ struct NoOperandMask {
|
||||
static constexpr uint32_t value = OneOperandMask<NoOperand>::value;
|
||||
};
|
||||
|
||||
uint32_t operand_mask(AddressingMode mode1, AddressingMode mode2) {
|
||||
uint32_t operand_mask(const AddressingMode mode1, const AddressingMode mode2) {
|
||||
return uint32_t((0x1'0000 << int(mode1)) | (0x0'0001 << int(mode2)));
|
||||
}
|
||||
|
||||
@ -70,7 +70,7 @@ uint32_t operand_mask(AddressingMode mode1, AddressingMode mode2) {
|
||||
/// a Preinstruction with an operation of AND, the former just happens to specify an
|
||||
/// immediate operand.
|
||||
template <Model model>
|
||||
constexpr Operation Predecoder<model>::operation(OpT op) {
|
||||
constexpr Operation Predecoder<model>::operation(const OpT op) {
|
||||
if(op <= OpMax) {
|
||||
return Operation(op);
|
||||
}
|
||||
@ -621,10 +621,10 @@ template <typename Predecoder<model>::OpT op> uint32_t Predecoder<model>::invali
|
||||
/// Provides a post-decoding validation step — primarily ensures that the prima facie addressing modes are supported by the operation.
|
||||
template <Model model>
|
||||
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,
|
||||
int additional_extension_words
|
||||
const AddressingMode op1_mode, const int op1_reg,
|
||||
const AddressingMode op2_mode, const int op2_reg,
|
||||
const Condition condition,
|
||||
const int additional_extension_words
|
||||
) {
|
||||
constexpr auto operation = Predecoder<model>::operation(op);
|
||||
|
||||
@ -656,7 +656,7 @@ template <typename Predecoder<model>::OpT op, bool validate> Preinstruction Pred
|
||||
/// 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 <typename Predecoder<model>::OpT op, bool validate> Preinstruction Predecoder<model>::decode(uint16_t instruction) {
|
||||
template <typename Predecoder<model>::OpT op, bool validate> Preinstruction Predecoder<model>::decode(const uint16_t instruction) {
|
||||
// Fields used pervasively below.
|
||||
//
|
||||
// Underlying assumption: the compiler will discard whatever of these
|
||||
@ -1273,7 +1273,7 @@ template <typename Predecoder<model>::OpT op, bool validate> Preinstruction Pred
|
||||
#define DecodeReq(x, y) if constexpr (x) Decode(y); break;
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decode0(uint16_t instruction) {
|
||||
Preinstruction Predecoder<model>::decode0(const uint16_t instruction) {
|
||||
using Op = Operation;
|
||||
|
||||
switch(instruction & 0xfff) {
|
||||
@ -1386,7 +1386,7 @@ Preinstruction Predecoder<model>::decode0(uint16_t instruction) {
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decode1(uint16_t instruction) {
|
||||
Preinstruction Predecoder<model>::decode1(const uint16_t instruction) {
|
||||
using Op = Operation;
|
||||
|
||||
// 4-116 (p220)
|
||||
@ -1394,7 +1394,7 @@ Preinstruction Predecoder<model>::decode1(uint16_t instruction) {
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decode2(uint16_t instruction) {
|
||||
Preinstruction Predecoder<model>::decode2(const uint16_t instruction) {
|
||||
using Op = Operation;
|
||||
|
||||
// 4-116 (p220)
|
||||
@ -1405,7 +1405,7 @@ Preinstruction Predecoder<model>::decode2(uint16_t instruction) {
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decode3(uint16_t instruction) {
|
||||
Preinstruction Predecoder<model>::decode3(const uint16_t instruction) {
|
||||
using Op = Operation;
|
||||
|
||||
// 4-116 (p220)
|
||||
@ -1416,7 +1416,7 @@ Preinstruction Predecoder<model>::decode3(uint16_t instruction) {
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decode4(uint16_t instruction) {
|
||||
Preinstruction Predecoder<model>::decode4(const uint16_t instruction) {
|
||||
using Op = Operation;
|
||||
|
||||
switch(instruction & 0xfff) {
|
||||
@ -1539,7 +1539,7 @@ Preinstruction Predecoder<model>::decode4(uint16_t instruction) {
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decode5(uint16_t instruction) {
|
||||
Preinstruction Predecoder<model>::decode5(const uint16_t instruction) {
|
||||
using Op = Operation;
|
||||
|
||||
switch(instruction & 0x1f8) {
|
||||
@ -1617,7 +1617,7 @@ Preinstruction Predecoder<model>::decode5(uint16_t instruction) {
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decode6(uint16_t instruction) {
|
||||
Preinstruction Predecoder<model>::decode6(const uint16_t instruction) {
|
||||
using Op = Operation;
|
||||
|
||||
switch(instruction & 0xf00) {
|
||||
@ -1649,7 +1649,7 @@ Preinstruction Predecoder<model>::decode6(uint16_t instruction) {
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decode7(uint16_t instruction) {
|
||||
Preinstruction Predecoder<model>::decode7(const uint16_t instruction) {
|
||||
// 4-134 (p238)
|
||||
if(!(instruction & 0x100)) {
|
||||
Decode(MOVEQ);
|
||||
@ -1659,7 +1659,7 @@ Preinstruction Predecoder<model>::decode7(uint16_t instruction) {
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decode8(uint16_t instruction) {
|
||||
Preinstruction Predecoder<model>::decode8(const uint16_t instruction) {
|
||||
using Op = Operation;
|
||||
|
||||
switch(instruction & 0x1f0) {
|
||||
@ -1689,7 +1689,7 @@ Preinstruction Predecoder<model>::decode8(uint16_t instruction) {
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decode9(uint16_t instruction) {
|
||||
Preinstruction Predecoder<model>::decode9(const uint16_t instruction) {
|
||||
using Op = Operation;
|
||||
|
||||
switch(instruction & 0x1f0) {
|
||||
@ -1721,12 +1721,12 @@ Preinstruction Predecoder<model>::decode9(uint16_t instruction) {
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decodeA(uint16_t) {
|
||||
Preinstruction Predecoder<model>::decodeA(const uint16_t) {
|
||||
return Preinstruction();
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decodeB(uint16_t instruction) {
|
||||
Preinstruction Predecoder<model>::decodeB(const uint16_t instruction) {
|
||||
using Op = Operation;
|
||||
|
||||
switch(instruction & 0x1f8) {
|
||||
@ -1760,7 +1760,7 @@ Preinstruction Predecoder<model>::decodeB(uint16_t instruction) {
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decodeC(uint16_t instruction) {
|
||||
Preinstruction Predecoder<model>::decodeC(const uint16_t instruction) {
|
||||
using Op = Operation;
|
||||
|
||||
// 4-105 (p209)
|
||||
@ -1795,7 +1795,7 @@ Preinstruction Predecoder<model>::decodeC(uint16_t instruction) {
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decodeD(uint16_t instruction) {
|
||||
Preinstruction Predecoder<model>::decodeD(const uint16_t instruction) {
|
||||
using Op = Operation;
|
||||
|
||||
switch(instruction & 0x1f0) {
|
||||
@ -1827,7 +1827,7 @@ Preinstruction Predecoder<model>::decodeD(uint16_t instruction) {
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decodeE(uint16_t instruction) {
|
||||
Preinstruction Predecoder<model>::decodeE(const uint16_t instruction) {
|
||||
using Op = Operation;
|
||||
|
||||
switch(instruction & 0xfc0) {
|
||||
@ -1900,7 +1900,7 @@ Preinstruction Predecoder<model>::decodeE(uint16_t instruction) {
|
||||
}
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decodeF(uint16_t) {
|
||||
Preinstruction Predecoder<model>::decodeF(const uint16_t) {
|
||||
return Preinstruction();
|
||||
}
|
||||
|
||||
@ -1910,7 +1910,7 @@ Preinstruction Predecoder<model>::decodeF(uint16_t) {
|
||||
// MARK: - Main decoder.
|
||||
|
||||
template <Model model>
|
||||
Preinstruction Predecoder<model>::decode(uint16_t instruction) {
|
||||
Preinstruction Predecoder<model>::decode(const uint16_t instruction) {
|
||||
// Divide first based on line.
|
||||
switch(instruction & 0xf000) {
|
||||
case 0x0000: return decode0(instruction);
|
||||
|
@ -45,12 +45,12 @@ void Executor<model, BusHandler>::reset() {
|
||||
}
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
void Executor<model, BusHandler>::signal_bus_error(FunctionCode code, uint32_t address) {
|
||||
void Executor<model, BusHandler>::signal_bus_error(const FunctionCode code, const uint32_t address) {
|
||||
throw AccessException(code, address, Exception::AccessFault);
|
||||
}
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
void Executor<model, BusHandler>::set_interrupt_level(int level) {
|
||||
void Executor<model, BusHandler>::set_interrupt_level(const int level) {
|
||||
state_.interrupt_input_ = level;
|
||||
state_.stopped &= !state_.status.would_accept_interrupt(level);
|
||||
}
|
||||
@ -147,7 +147,7 @@ void Executor<model, BusHandler>::set_state(const RegisterSet &state) {
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
template <typename IntT>
|
||||
IntT Executor<model, BusHandler>::State::read(uint32_t address, bool is_from_pc) {
|
||||
IntT Executor<model, BusHandler>::State::read(const uint32_t address, const bool is_from_pc) {
|
||||
const auto code = FunctionCode((active_stack_pointer << 2) | 1 << int(is_from_pc));
|
||||
if(model == Model::M68000 && sizeof(IntT) > 1 && address & 1) {
|
||||
throw AccessException(code, address, Exception::AddressError | (int(is_from_pc) << 3) | (1 << 4));
|
||||
@ -158,7 +158,7 @@ IntT Executor<model, BusHandler>::State::read(uint32_t address, bool is_from_pc)
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
template <typename IntT>
|
||||
void Executor<model, BusHandler>::State::write(uint32_t address, IntT value) {
|
||||
void Executor<model, BusHandler>::State::write(const uint32_t address, const IntT value) {
|
||||
const auto code = FunctionCode((active_stack_pointer << 2) | 1);
|
||||
if(model == Model::M68000 && sizeof(IntT) > 1 && address & 1) {
|
||||
throw AccessException(code, address, Exception::AddressError);
|
||||
@ -168,7 +168,7 @@ void Executor<model, BusHandler>::State::write(uint32_t address, IntT value) {
|
||||
}
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
void Executor<model, BusHandler>::State::read(DataSize size, uint32_t address, CPU::SlicedInt32 &value) {
|
||||
void Executor<model, BusHandler>::State::read(const DataSize size, const uint32_t address, CPU::SlicedInt32 &value) {
|
||||
switch(size) {
|
||||
case DataSize::Byte: value.b = read<uint8_t>(address); break;
|
||||
case DataSize::Word: value.w = read<uint16_t>(address); break;
|
||||
@ -177,7 +177,7 @@ void Executor<model, BusHandler>::State::read(DataSize size, uint32_t address, C
|
||||
}
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
void Executor<model, BusHandler>::State::write(DataSize size, uint32_t address, CPU::SlicedInt32 value) {
|
||||
void Executor<model, BusHandler>::State::write(const DataSize size, const uint32_t address, CPU::SlicedInt32 value) {
|
||||
switch(size) {
|
||||
case DataSize::Byte: write<uint8_t>(address, value.b); break;
|
||||
case DataSize::Word: write<uint16_t>(address, value.w); break;
|
||||
@ -266,7 +266,7 @@ uint32_t Executor<model, BusHandler>::State::index_8bitdisplacement(uint32_t bas
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
typename Executor<model, BusHandler>::State::EffectiveAddress
|
||||
Executor<model, BusHandler>::State::calculate_effective_address(Preinstruction instruction, uint16_t opcode, int index) {
|
||||
Executor<model, BusHandler>::State::calculate_effective_address(const Preinstruction instruction, const uint16_t opcode, const int index) {
|
||||
EffectiveAddress ea;
|
||||
|
||||
switch(instruction.mode(index)) {
|
||||
@ -474,7 +474,7 @@ void Executor<model, BusHandler>::State::run(int &count) {
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
template <bool use_current_instruction_pc>
|
||||
void Executor<model, BusHandler>::State::raise_exception(int index) {
|
||||
void Executor<model, BusHandler>::State::raise_exception(const int index) {
|
||||
const uint32_t address = index << 2;
|
||||
|
||||
// Grab the status to store, then switch into supervisor mode
|
||||
@ -519,40 +519,40 @@ void Executor<model, BusHandler>::State::reset() {
|
||||
}
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
void Executor<model, BusHandler>::State::jmp(uint32_t address) {
|
||||
void Executor<model, BusHandler>::State::jmp(const uint32_t address) {
|
||||
program_counter.l = address;
|
||||
}
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
template <typename IntT> void Executor<model, BusHandler>::State::complete_bcc(bool branch, IntT offset) {
|
||||
template <typename IntT> void Executor<model, BusHandler>::State::complete_bcc(const bool branch, const IntT offset) {
|
||||
if(branch) {
|
||||
program_counter.l = instruction_address + offset + 2;
|
||||
}
|
||||
}
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
void Executor<model, BusHandler>::State::complete_dbcc(bool matched_condition, bool overflowed, int16_t offset) {
|
||||
void Executor<model, BusHandler>::State::complete_dbcc(const bool matched_condition, const bool overflowed, const int16_t offset) {
|
||||
if(!matched_condition && !overflowed) {
|
||||
program_counter.l = instruction_address + offset + 2;
|
||||
}
|
||||
}
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
void Executor<model, BusHandler>::State::bsr(uint32_t offset) {
|
||||
void Executor<model, BusHandler>::State::bsr(const uint32_t offset) {
|
||||
sp.l -= 4;
|
||||
write<uint32_t>(sp.l, program_counter.l);
|
||||
program_counter.l = instruction_address + offset + 2;
|
||||
}
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
void Executor<model, BusHandler>::State::jsr(uint32_t address) {
|
||||
void Executor<model, BusHandler>::State::jsr(const uint32_t address) {
|
||||
sp.l -= 4;
|
||||
write<uint32_t>(sp.l, program_counter.l);
|
||||
program_counter.l = address;
|
||||
}
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
void Executor<model, BusHandler>::State::link(Preinstruction instruction, uint32_t offset) {
|
||||
void Executor<model, BusHandler>::State::link(const Preinstruction instruction, const uint32_t offset) {
|
||||
const auto reg = 8 + instruction.reg<0>();
|
||||
|
||||
sp.l -= 4;
|
||||
@ -569,7 +569,7 @@ void Executor<model, BusHandler>::State::unlink(uint32_t &address) {
|
||||
}
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
void Executor<model, BusHandler>::State::pea(uint32_t address) {
|
||||
void Executor<model, BusHandler>::State::pea(const uint32_t address) {
|
||||
sp.l -= 4;
|
||||
write<uint32_t>(sp.l, address);
|
||||
}
|
||||
@ -595,7 +595,7 @@ void Executor<model, BusHandler>::State::rts() {
|
||||
}
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
void Executor<model, BusHandler>::State::tas(Preinstruction instruction, uint32_t address) {
|
||||
void Executor<model, BusHandler>::State::tas(const Preinstruction instruction, const uint32_t address) {
|
||||
uint8_t value;
|
||||
if(instruction.mode<0>() != AddressingMode::DataRegisterDirect) {
|
||||
value = read<uint8_t>(address);
|
||||
@ -611,7 +611,7 @@ void Executor<model, BusHandler>::State::tas(Preinstruction instruction, uint32_
|
||||
}
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
void Executor<model, BusHandler>::State::move_to_usp(uint32_t address) {
|
||||
void Executor<model, BusHandler>::State::move_to_usp(const uint32_t address) {
|
||||
stack_pointers[0].l = address;
|
||||
}
|
||||
|
||||
@ -622,7 +622,7 @@ void Executor<model, BusHandler>::State::move_from_usp(uint32_t &address) {
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
template <typename IntT>
|
||||
void Executor<model, BusHandler>::State::movep(Preinstruction instruction, uint32_t source, uint32_t dest) {
|
||||
void Executor<model, BusHandler>::State::movep(const Preinstruction instruction, const uint32_t source, const uint32_t dest) {
|
||||
if(instruction.mode<0>() == AddressingMode::DataRegisterDirect) {
|
||||
// Move register to memory.
|
||||
const uint32_t reg = source;
|
||||
@ -664,7 +664,7 @@ void Executor<model, BusHandler>::State::movep(Preinstruction instruction, uint3
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
template <typename IntT>
|
||||
void Executor<model, BusHandler>::State::movem_toM(Preinstruction instruction, uint32_t source, uint32_t dest) {
|
||||
void Executor<model, BusHandler>::State::movem_toM(const Preinstruction instruction, uint32_t source, uint32_t dest) {
|
||||
// Move registers to memory. This is the only permitted use of the predecrement mode,
|
||||
// which reverses output order.
|
||||
|
||||
@ -711,7 +711,7 @@ void Executor<model, BusHandler>::State::movem_toM(Preinstruction instruction, u
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
template <typename IntT>
|
||||
void Executor<model, BusHandler>::State::movem_toR(Preinstruction instruction, uint32_t source, uint32_t dest) {
|
||||
void Executor<model, BusHandler>::State::movem_toR(const Preinstruction instruction, uint32_t source, uint32_t dest) {
|
||||
// Move memory to registers.
|
||||
//
|
||||
// A 68000 convention has been broken here; the instruction form is:
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
namespace InstructionSet::M68k {
|
||||
|
||||
template <Model model, Operation t_operation> constexpr uint8_t operand_flags(Operation r_operation) {
|
||||
template <Model model, Operation t_operation> constexpr uint8_t operand_flags(const Operation r_operation) {
|
||||
switch((t_operation != Operation::Undefined) ? t_operation : r_operation) {
|
||||
default:
|
||||
assert(false);
|
||||
|
@ -11,7 +11,7 @@
|
||||
namespace InstructionSet::M68k {
|
||||
|
||||
template <Operation t_operation>
|
||||
constexpr DataSize operand_size(Operation r_operation) {
|
||||
constexpr DataSize operand_size(const Operation r_operation) {
|
||||
switch((t_operation == Operation::Undefined) ? r_operation : t_operation) {
|
||||
// These are given a value arbitrarily, to
|
||||
// complete the switch statement.
|
||||
|
@ -18,10 +18,10 @@
|
||||
namespace InstructionSet::M68k {
|
||||
|
||||
/// Sign-extend @c x to 32 bits and return as an unsigned 32-bit int.
|
||||
inline uint32_t u_extend16(uint16_t x) { return uint32_t(int16_t(x)); }
|
||||
inline uint32_t u_extend16(const uint16_t x) { return uint32_t(int16_t(x)); }
|
||||
|
||||
/// Sign-extend @c x to 32 bits and return as a signed 32-bit int.
|
||||
inline int32_t s_extend16(uint16_t x) { return int32_t(int16_t(x)); }
|
||||
inline int32_t s_extend16(const uint16_t x) { return int32_t(int16_t(x)); }
|
||||
|
||||
namespace Primitive {
|
||||
|
||||
@ -29,7 +29,7 @@ namespace Primitive {
|
||||
/// updating @c status. @c is_extend indicates whether this is an extend operation (e.g. ADDX)
|
||||
/// or a plain one (e.g. ADD).
|
||||
template <bool is_add, bool is_extend, typename IntT>
|
||||
static void add_sub(IntT source, IntT &destination, Status &status) {
|
||||
static void add_sub(const IntT source, IntT &destination, Status &status) {
|
||||
static_assert(!std::numeric_limits<IntT>::is_signed);
|
||||
|
||||
IntT result = is_add ?
|
||||
@ -67,7 +67,7 @@ static void add_sub(IntT source, IntT &destination, Status &status) {
|
||||
///
|
||||
/// @discussion The slightly awkward abandonment of source, destination permits the use of this for both
|
||||
/// SBCD and NBCD.
|
||||
inline void sbcd(uint8_t rhs, uint8_t lhs, uint8_t &destination, Status &status) {
|
||||
inline void sbcd(const uint8_t rhs, const uint8_t lhs, uint8_t &destination, Status &status) {
|
||||
const int extend = (status.extend_flag ? 1 : 0);
|
||||
const int unadjusted_result = lhs - rhs - extend;
|
||||
|
||||
@ -92,7 +92,7 @@ inline void sbcd(uint8_t rhs, uint8_t lhs, uint8_t &destination, Status &status)
|
||||
/// Perform the bitwise operation defined by @c operation on @c source and @c destination and update @c status.
|
||||
/// Bitwise operations are any of the byte, word or long versions of AND, OR and EOR.
|
||||
template <Operation operation, typename IntT>
|
||||
void bitwise(IntT source, IntT &destination, Status &status) {
|
||||
void bitwise(const IntT source, IntT &destination, Status &status) {
|
||||
static_assert(
|
||||
operation == Operation::ANDb || operation == Operation::ANDw || operation == Operation::ANDl ||
|
||||
operation == Operation::ORb || operation == Operation::ORw || operation == Operation::ORl ||
|
||||
@ -117,7 +117,7 @@ void bitwise(IntT source, IntT &destination, Status &status) {
|
||||
|
||||
/// Compare of @c source to @c destination, setting zero, carry, negative and overflow flags.
|
||||
template <typename IntT>
|
||||
void compare(IntT source, IntT destination, Status &status) {
|
||||
void compare(const IntT source, const IntT destination, Status &status) {
|
||||
const IntT result = destination - source;
|
||||
status.carry_flag = result > destination;
|
||||
status.set_neg_zero(result);
|
||||
@ -126,14 +126,14 @@ void compare(IntT source, IntT destination, Status &status) {
|
||||
|
||||
/// @returns the name of the bit to be used as a mask for BCLR, BCHG, BSET or BTST for
|
||||
/// @c instruction given @c source.
|
||||
inline uint32_t mask_bit(const Preinstruction &instruction, uint32_t source) {
|
||||
inline uint32_t mask_bit(const Preinstruction &instruction, const uint32_t source) {
|
||||
return source & (instruction.mode<1>() == AddressingMode::DataRegisterDirect ? 31 : 7);
|
||||
}
|
||||
|
||||
/// Perform a BCLR, BCHG or BSET as specified by @c operation and described by @c instruction, @c source and @c destination, updating @c destination and @c status.
|
||||
/// Also makes an appropriate notification to the @c flow_controller.
|
||||
template <Operation operation, typename FlowController>
|
||||
void bit_manipulate(const Preinstruction &instruction, uint32_t source, uint32_t &destination, Status &status, FlowController &flow_controller) {
|
||||
void bit_manipulate(const Preinstruction &instruction, const uint32_t source, uint32_t &destination, Status &status, FlowController &flow_controller) {
|
||||
static_assert(
|
||||
operation == Operation::BCLR ||
|
||||
operation == Operation::BCHG ||
|
||||
@ -157,7 +157,7 @@ template <typename IntT> void clear(IntT &destination, Status &status) {
|
||||
|
||||
/// Perform an ANDI, EORI or ORI to either SR or CCR, notifying @c flow_controller if appropriate.
|
||||
template <Operation operation, typename FlowController>
|
||||
void apply_sr_ccr(uint16_t source, Status &status, FlowController &flow_controller) {
|
||||
void apply_sr_ccr(const uint16_t source, Status &status, FlowController &flow_controller) {
|
||||
static_assert(
|
||||
operation == Operation::ANDItoSR || operation == Operation::ANDItoCCR ||
|
||||
operation == Operation::EORItoSR || operation == Operation::EORItoCCR ||
|
||||
@ -195,7 +195,7 @@ void apply_sr_ccr(uint16_t source, Status &status, FlowController &flow_controll
|
||||
|
||||
/// Perform a MULU or MULS between @c source and @c destination, updating @c status and notifying @c flow_controller.
|
||||
template <bool is_mulu, typename FlowController>
|
||||
void multiply(uint16_t source, uint32_t &destination, Status &status, FlowController &flow_controller) {
|
||||
void multiply(const uint16_t source, uint32_t &destination, Status &status, FlowController &flow_controller) {
|
||||
if constexpr (is_mulu) {
|
||||
destination = source * uint16_t(destination);
|
||||
} else {
|
||||
@ -213,7 +213,7 @@ void multiply(uint16_t source, uint32_t &destination, Status &status, FlowContro
|
||||
|
||||
/// Announce a DIVU or DIVS to @c flow_controller.
|
||||
template <bool is_divu, bool did_overflow, typename IntT, typename FlowController>
|
||||
void did_divide(IntT dividend, IntT divisor, FlowController &flow_controller) {
|
||||
void did_divide(const IntT dividend, const IntT divisor, FlowController &flow_controller) {
|
||||
if constexpr (is_divu) {
|
||||
flow_controller.template did_divu<did_overflow>(dividend, divisor);
|
||||
} else {
|
||||
@ -223,7 +223,7 @@ void did_divide(IntT dividend, IntT divisor, FlowController &flow_controller) {
|
||||
|
||||
/// Perform a DIVU or DIVS between @c source and @c destination, updating @c status and notifying @c flow_controller.
|
||||
template <bool is_divu, typename Int16, typename Int32, typename FlowController>
|
||||
void divide(uint16_t source, uint32_t &destination, Status &status, FlowController &flow_controller) {
|
||||
void divide(const uint16_t source, uint32_t &destination, Status &status, FlowController &flow_controller) {
|
||||
status.carry_flag = 0;
|
||||
|
||||
const auto dividend = Int32(destination);
|
||||
@ -254,7 +254,7 @@ void divide(uint16_t source, uint32_t &destination, Status &status, FlowControll
|
||||
}
|
||||
|
||||
/// Move @c source to @c destination, updating @c status.
|
||||
template <typename IntT> void move(IntT source, IntT &destination, Status &status) {
|
||||
template <typename IntT> void move(const IntT source, IntT &destination, Status &status) {
|
||||
destination = source;
|
||||
status.set_neg_zero(destination);
|
||||
status.overflow_flag = status.carry_flag = 0;
|
||||
@ -277,20 +277,20 @@ template <bool is_extend, typename IntT> void negative(IntT &source, Status &sta
|
||||
}
|
||||
|
||||
/// Perform TST.[b/l/w] with @c source, updating @c status.
|
||||
template <typename IntT> void test(IntT source, Status &status) {
|
||||
template <typename IntT> void test(const IntT source, Status &status) {
|
||||
status.carry_flag = status.overflow_flag = 0;
|
||||
status.set_neg_zero(source);
|
||||
}
|
||||
|
||||
/// Decodes the proper shift distance from @c source, notifying the @c flow_controller.
|
||||
template <typename IntT, typename FlowController> int shift_count(uint8_t source, FlowController &flow_controller) {
|
||||
template <typename IntT, typename FlowController> int shift_count(const uint8_t source, FlowController &flow_controller) {
|
||||
const int count = source & 63;
|
||||
flow_controller.template did_shift<IntT>(count);
|
||||
return count;
|
||||
}
|
||||
|
||||
/// Perform an arithmetic or logical shift, i.e. any of LSL, LSR, ASL or ASR.
|
||||
template <Operation operation, typename IntT, typename FlowController> void shift(uint32_t source, IntT &destination, Status &status, FlowController &flow_controller) {
|
||||
template <Operation operation, typename IntT, typename FlowController> void shift(const uint32_t source, IntT &destination, Status &status, FlowController &flow_controller) {
|
||||
static_assert(
|
||||
operation == Operation::ASLb || operation == Operation::ASLw || operation == Operation::ASLl ||
|
||||
operation == Operation::ASRb || operation == Operation::ASRw || operation == Operation::ASRl ||
|
||||
@ -384,7 +384,7 @@ template <Operation operation, typename IntT, typename FlowController> void shif
|
||||
}
|
||||
|
||||
/// Perform a rotate without extend, i.e. any of RO[L/R].[b/w/l].
|
||||
template <Operation operation, typename IntT, typename FlowController> void rotate(uint32_t source, IntT &destination, Status &status, FlowController &flow_controller) {
|
||||
template <Operation operation, typename IntT, typename FlowController> void rotate(const uint32_t source, IntT &destination, Status &status, FlowController &flow_controller) {
|
||||
static_assert(
|
||||
operation == Operation::ROLb || operation == Operation::ROLw || operation == Operation::ROLl ||
|
||||
operation == Operation::RORb || operation == Operation::RORw || operation == Operation::RORl
|
||||
@ -425,7 +425,7 @@ template <Operation operation, typename IntT, typename FlowController> void rota
|
||||
}
|
||||
|
||||
/// Perform a rotate-through-extend, i.e. any of ROX[L/R].[b/w/l].
|
||||
template <Operation operation, typename IntT, typename FlowController> void rox(uint32_t source, IntT &destination, Status &status, FlowController &flow_controller) {
|
||||
template <Operation operation, typename IntT, typename FlowController> void rox(const uint32_t source, IntT &destination, Status &status, FlowController &flow_controller) {
|
||||
static_assert(
|
||||
operation == Operation::ROXLb || operation == Operation::ROXLw || operation == Operation::ROXLl ||
|
||||
operation == Operation::ROXRb || operation == Operation::ROXRw || operation == Operation::ROXRl
|
||||
@ -496,7 +496,7 @@ template <
|
||||
Model model,
|
||||
typename FlowController,
|
||||
Operation operation = Operation::Undefined
|
||||
> void perform(Preinstruction instruction, CPU::SlicedInt32 &src, CPU::SlicedInt32 &dest, Status &status, FlowController &flow_controller) {
|
||||
> void perform(const Preinstruction instruction, CPU::SlicedInt32 &src, CPU::SlicedInt32 &dest, Status &status, FlowController &flow_controller) {
|
||||
|
||||
switch((operation != Operation::Undefined) ? operation : instruction.operation) {
|
||||
/*
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
using namespace InstructionSet::M68k;
|
||||
|
||||
std::string Preinstruction::operand_description(int index, int opcode) const {
|
||||
std::string Preinstruction::operand_description(const int index, const int opcode) const {
|
||||
switch(mode(index)) {
|
||||
default: assert(false);
|
||||
|
||||
@ -59,7 +59,7 @@ std::string Preinstruction::operand_description(int index, int opcode) const {
|
||||
|
||||
namespace {
|
||||
|
||||
const char *_to_string(Operation operation, bool is_quick) {
|
||||
const char *_to_string(const Operation operation, const bool is_quick) {
|
||||
switch(operation) {
|
||||
case Operation::Undefined: return "None";
|
||||
case Operation::NOP: return "NOP";
|
||||
@ -295,11 +295,11 @@ const char *_to_string(Operation operation, bool is_quick) {
|
||||
|
||||
}
|
||||
|
||||
const char *InstructionSet::M68k::to_string(Operation operation) {
|
||||
const char *InstructionSet::M68k::to_string(const Operation operation) {
|
||||
return _to_string(operation, false);
|
||||
}
|
||||
|
||||
std::string Preinstruction::to_string(int opcode) const {
|
||||
std::string Preinstruction::to_string(const int opcode) const {
|
||||
if(operation == Operation::Undefined) return "None";
|
||||
|
||||
const char *const instruction = _to_string(operation, mode<0>() == AddressingMode::Quick);
|
||||
|
@ -239,7 +239,7 @@ template <Operation t_operation = Operation::Undefined>
|
||||
constexpr DataSize operand_size(Operation operation = Operation::Undefined);
|
||||
|
||||
template <Operation t_op = Operation::Undefined>
|
||||
constexpr uint32_t quick(uint16_t instruction, Operation r_op = Operation::Undefined) {
|
||||
constexpr uint32_t quick(const uint16_t instruction, const Operation r_op = Operation::Undefined) {
|
||||
switch((t_op != Operation::Undefined) ? t_op : r_op) {
|
||||
case Operation::Bccb:
|
||||
case Operation::BSRb:
|
||||
@ -385,7 +385,7 @@ class Preinstruction {
|
||||
// if using the runtime versions then results for indices
|
||||
// other than 0 and 1 are undefined.
|
||||
|
||||
AddressingMode mode(int index) const {
|
||||
AddressingMode mode(const int index) const {
|
||||
return AddressingMode(operands_[index] >> 3);
|
||||
}
|
||||
template <int index> AddressingMode mode() const {
|
||||
@ -394,7 +394,7 @@ class Preinstruction {
|
||||
}
|
||||
return mode(index);
|
||||
}
|
||||
int reg(int index) const {
|
||||
int reg(const int index) const {
|
||||
return operands_[index] & 7;
|
||||
}
|
||||
template <int index> int reg() const {
|
||||
@ -407,7 +407,7 @@ class Preinstruction {
|
||||
/// @returns 0–7 to indicate data registers 0 to 7, or 8–15 to indicate address registers 0 to 7 respectively.
|
||||
/// Provides undefined results if the addressing mode is not either @c DataRegisterDirect or
|
||||
/// @c AddressRegisterDirect.
|
||||
int lreg(int index) const {
|
||||
int lreg(const int index) const {
|
||||
return operands_[index] & 0xf;
|
||||
}
|
||||
|
||||
@ -415,6 +415,7 @@ class Preinstruction {
|
||||
bool requires_supervisor() const {
|
||||
return flags_ & Flags::IsSupervisor;
|
||||
}
|
||||
|
||||
/// @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
|
||||
@ -425,14 +426,17 @@ class Preinstruction {
|
||||
bool requires_further_extension() const {
|
||||
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.
|
||||
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 {
|
||||
|
@ -140,13 +140,13 @@ struct NullFlowController {
|
||||
/// The receiver is responsible for updating the address register if applicable.
|
||||
///
|
||||
/// @c IntT may be either uint16_t or uint32_t.
|
||||
template <typename IntT> void movem_toR(Preinstruction instruction, uint32_t mask, uint32_t address);
|
||||
template <typename IntT> void movem_toR(Preinstruction, uint32_t mask, uint32_t address);
|
||||
|
||||
/// Raises a short-form exception using @c vector. If @c use_current_instruction_pc is @c true,
|
||||
/// the program counter for the current instruction is included in the resulting stack frame. Otherwise the program
|
||||
/// counter for the next instruction is used.
|
||||
template <bool use_current_instruction_pc = true>
|
||||
void raise_exception([[maybe_unused]] int vector);
|
||||
void raise_exception(int vector);
|
||||
};
|
||||
|
||||
/// Performs @c instruction using @c source and @c dest (one or both of which may be ignored as per
|
||||
|
@ -53,13 +53,13 @@ struct Status {
|
||||
FlagT negative_flag = 0; // The negative flag is set if and only this value is non-zero.
|
||||
|
||||
/// Sets the negative flag per @c value
|
||||
template <typename IntT> void set_negative(IntT value) {
|
||||
template <typename IntT> void set_negative(const IntT value) {
|
||||
constexpr auto top_bit = IntT(1 << ((sizeof(IntT) * 8) - 1));
|
||||
negative_flag = value & top_bit;
|
||||
}
|
||||
|
||||
/// Sets both the negative and zero flags according to @c value.
|
||||
template <typename IntT> void set_neg_zero(IntT value) {
|
||||
template <typename IntT> void set_neg_zero(const IntT value) {
|
||||
zero_result = value;
|
||||
set_negative(value);
|
||||
}
|
||||
@ -75,7 +75,7 @@ struct Status {
|
||||
}
|
||||
|
||||
/// Sets the current condition codes.
|
||||
constexpr void set_ccr(uint16_t ccr) {
|
||||
constexpr void set_ccr(const uint16_t ccr) {
|
||||
carry_flag = ccr & ConditionCode::Carry;
|
||||
overflow_flag = ccr & ConditionCode::Overflow;
|
||||
zero_result = ~ccr & ConditionCode::Zero;
|
||||
@ -95,7 +95,7 @@ struct Status {
|
||||
|
||||
/// Sets the current value of the status register;
|
||||
/// @returns @c true if the processor finishes in supervisor mode; @c false otherwise.
|
||||
constexpr bool set_status(uint16_t status) {
|
||||
constexpr bool set_status(const uint16_t status) {
|
||||
set_ccr(status);
|
||||
|
||||
interrupt_level = (status >> 8) & 7;
|
||||
@ -110,7 +110,7 @@ struct Status {
|
||||
/// interrupt level.
|
||||
///
|
||||
/// @returns The status prior to those changes.
|
||||
uint16_t begin_exception(int new_interrupt_level = -1) {
|
||||
uint16_t begin_exception(const int new_interrupt_level = -1) {
|
||||
const uint16_t initial_status = status();
|
||||
|
||||
if(new_interrupt_level >= 0) {
|
||||
@ -123,7 +123,7 @@ struct Status {
|
||||
}
|
||||
|
||||
/// Evaluates @c condition.
|
||||
constexpr bool evaluate_condition(Condition condition) const {
|
||||
constexpr bool evaluate_condition(const Condition condition) const {
|
||||
switch(condition) {
|
||||
default:
|
||||
case Condition::True: return true;
|
||||
@ -150,7 +150,7 @@ struct Status {
|
||||
}
|
||||
|
||||
/// @returns @c true if an interrupt at level @c level should be accepted; @c false otherwise.
|
||||
constexpr bool would_accept_interrupt(int level) const {
|
||||
constexpr bool would_accept_interrupt(const int level) const {
|
||||
// TODO: is level seven really non-maskable? If so then what mechanism prevents
|
||||
// rapid stack overflow upon a level-seven interrupt?
|
||||
return level > interrupt_level;
|
||||
|
Loading…
x
Reference in New Issue
Block a user