1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-25 18:30:07 +00:00

Start reforming; data size plus register aren't independent in finding a source.

This commit is contained in:
Thomas Harte 2023-10-05 16:49:02 -04:00
parent 15acb1fc7c
commit eb100e3b29
4 changed files with 85 additions and 65 deletions

View File

@ -182,65 +182,87 @@ void add(IntT &destination, IntT source, Status &status) {
template <
Model model,
Operation operation,
DataSize data_size,
typename FlowControllerT
typename InstructionT,
typename FlowControllerT,
typename RegistersT,
typename MemoryT,
typename IOT
> void perform(
CPU::RegisterPair16 &destination,
CPU::RegisterPair16 &source,
const InstructionT &instruction,
Status &status,
FlowControllerT &flow_controller
[[maybe_unused]] FlowControllerT &flow_controller,
RegistersT &registers,
[[maybe_unused]] MemoryT &memory,
[[maybe_unused]] IOT &io
) {
switch(operation) {
case Operation::AAA: Primitive::aaa(destination, status); break;
case Operation::AAD: Primitive::aad(destination, source.halves.low, status); break;
case Operation::AAM: Primitive::aam(destination, source.halves.low, status); break;
case Operation::AAS: Primitive::aas(destination, status); break;
using IntT = typename DataSizeType<data_size>::type;
case Operation::ADC:
static_assert(operation != Operation::ADC || data_size == DataSize::Byte || data_size == DataSize::Word);
switch(data_size) {
case DataSize::Byte: Primitive::adc(destination.halves.low, source.halves.low, status); break;
case DataSize::Word: Primitive::adc(destination.full, source.full, status); break;
}
break;
case Operation::ADD:
static_assert(operation != Operation::ADD || data_size == DataSize::Byte || data_size == DataSize::Word);
switch(data_size) {
case DataSize::Byte: Primitive::add(destination.halves.low, source.halves.low, status); break;
case DataSize::Word: Primitive::add(destination.full, source.full, status); break;
}
break;
// Establish source() and destination() shorthand to fetch data if necessary.
IntT fetched_data;
bool needs_writeback = false;
auto data = [&](DataPointer source) -> IntT& {
// TODO.
return fetched_data;
};
auto source = [&]() -> IntT& { return data(instruction.source()); };
auto destination = [&]() -> IntT& { return data(instruction.destination()); };
// Guide to the below:
//
// * use hard-coded register names where appropriate;
// * return directly if there is definitely no possible write back to RAM;
// * otherwise use the source() and destination() lambdas, and break in order to allow a writeback if necessary.
switch(instruction.operation) {
case Operation::AAA: Primitive::aaa(registers.ax(), status); return;
case Operation::AAD: Primitive::aad(registers.ax(), instruction.immediate(), status); return;
case Operation::AAM: Primitive::aam(registers.ax(), instruction.immediate(), status); return;
case Operation::AAS: Primitive::aas(registers.ax(), status); return;
case Operation::ADC: Primitive::adc(destination(), source(), status); break;
case Operation::ADD: Primitive::add(destination(), source(), status); break;
}
(void)flow_controller;
// Write to memory if required to complete this operation.
if(needs_writeback) {
// TODO.
}
}
/*template <
template <
Model model,
typename InstructionT,
typename FlowControllerT,
typename DataPointerResolverT,
typename RegistersT,
typename MemoryT,
typename IOT,
Operation operation
typename IOT
> void perform(
const InstructionT &instruction,
Status &status,
FlowControllerT &flow_controller,
DataPointerResolverT &resolver,
RegistersT &registers,
MemoryT &memory,
IOT &io
) {
switch((operation != Operation::Invalid) ? operation : instruction.operation) {
default:
assert(false);
return;
// Dispatch to a function just like this that is specialised on data size.
// Fetching will occur in that specialised function, per the overlapping
// meaning of register names.
switch(instruction.operation_size()) {
case DataSize::Byte:
perform<model, DataSize::Byte>(instruction, status, flow_controller, registers, memory, io);
break;
case DataSize::Word:
perform<model, DataSize::Word>(instruction, status, flow_controller, registers, memory, io);
break;
case DataSize::DWord:
perform<model, DataSize::DWord>(instruction, status, flow_controller, registers, memory, io);
break;
case DataSize::None:
perform<model, DataSize::None>(instruction, status, flow_controller, registers, memory, io);
break;
}
}*/
}
}

View File

@ -370,6 +370,10 @@ enum class DataSize: uint8_t {
None = 3,
};
template <DataSize size> struct DataSizeType { using type = uint8_t; };
template <> struct DataSizeType<DataSize::Word> { using type = uint16_t; };
template <> struct DataSizeType<DataSize::DWord> { using type = uint32_t; };
constexpr int byte_size(DataSize size) {
return (1 << int(size)) & 7;
}

View File

@ -16,33 +16,27 @@
namespace InstructionSet::x86 {
/// Performs @c instruction using @c resolver to obtain to query @c registers and/or @c memory as required, using @c io for port input/output,
/// Performs @c instruction querying @c registers and/or @c memory as required, using @c io for port input/output,
/// and providing any flow control effects to @c flow_controller.
///
/// Any change in processor status will be applied to @c status.
///
/// If the template parameter @c operation is not @c Operation::Undefined then that operation will be performed, ignoring
/// whatever is specifed in @c instruction.
template <
Model model,
typename InstructionT,
typename FlowControllerT,
typename DataPointerResolverT,
typename RegistersT,
typename MemoryT,
typename IOT,
Operation operation = Operation::Invalid
typename IOT
> void perform(
const InstructionT &instruction,
Status &status,
FlowControllerT &flow_controller,
DataPointerResolverT &resolver,
RegistersT &registers,
MemoryT &memory,
IOT &io
);
template <
/*template <
Model model,
Operation operation,
DataSize data_size,
@ -64,7 +58,7 @@ template <
CPU::RegisterPair16 &source,
Status &status,
FlowControllerT &flow_controller
);
);*/
}

View File

@ -187,25 +187,25 @@ constexpr char TestSuiteHome[] = "/Users/tharte/Projects/ProcessorTests/8088/v1"
}
- (void)testExecution {
CPU::RegisterPair16 source, dest;
InstructionSet::x86::Status status;
struct NoFlow {
} flow_controller;
dest.full = 0xff;
source.full = 10;
InstructionSet::x86::perform<
InstructionSet::x86::Model::i8086,
InstructionSet::x86::Operation::ADD,
InstructionSet::x86::DataSize::Byte
>(
dest,
source,
status,
flow_controller
);
// CPU::RegisterPair16 source, dest;
// InstructionSet::x86::Status status;
// struct NoFlow {
// } flow_controller;
//
// dest.full = 0xff;
// source.full = 10;
//
// InstructionSet::x86::perform<
// InstructionSet::x86::Model::i8086,
// InstructionSet::x86::Operation::ADD,
// InstructionSet::x86::DataSize::Byte
// >(
// dest,
// source,
// status,
// flow_controller
// );
//
}
@end