1
0
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:
Thomas Harte 2024-10-13 21:34:01 -04:00
parent 9c550a8154
commit a7d2b0f63b
9 changed files with 87 additions and 83 deletions

View File

@ -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);

View File

@ -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:

View File

@ -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);

View File

@ -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.

View File

@ -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) {
/*

View File

@ -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);

View File

@ -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 07 to indicate data registers 0 to 7, or 815 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 {

View File

@ -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

View File

@ -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;