mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Take a swing at LEA r16, r16.
This commit is contained in:
parent
599c123b36
commit
817a30332c
@ -55,36 +55,8 @@ uint32_t address(
|
||||
return address + *resolve<model, uint16_t>(instruction, pointer.base(), pointer, registers, memory);
|
||||
}
|
||||
|
||||
template <Model model, typename IntT, typename InstructionT, typename RegistersT, typename MemoryT>
|
||||
uint32_t address(
|
||||
InstructionT &instruction,
|
||||
DataPointer pointer,
|
||||
RegistersT ®isters,
|
||||
MemoryT &memory
|
||||
) {
|
||||
switch(pointer.source<false>()) {
|
||||
default: return 0;
|
||||
case Source::Indirect: return address<model, Source::Indirect, IntT>(instruction, pointer, registers, memory);
|
||||
case Source::IndirectNoBase: return address<model, Source::IndirectNoBase, IntT>(instruction, pointer, registers, memory);
|
||||
case Source::DirectAddress: return address<model, Source::DirectAddress, IntT>(instruction, pointer, registers, memory);
|
||||
}
|
||||
}
|
||||
|
||||
template <Model model, typename IntT, typename InstructionT, typename RegistersT, typename MemoryT>
|
||||
IntT *resolve(
|
||||
InstructionT &instruction,
|
||||
Source source,
|
||||
DataPointer pointer,
|
||||
RegistersT ®isters,
|
||||
MemoryT &memory,
|
||||
IntT *none,
|
||||
IntT *immediate
|
||||
) {
|
||||
// Rules:
|
||||
//
|
||||
// * if this is a memory access, set target_address and break;
|
||||
// * otherwise return the appropriate value.
|
||||
uint32_t target_address;
|
||||
template <Model model, typename IntT, Source source, typename RegistersT>
|
||||
IntT *register_(RegistersT ®isters) {
|
||||
switch(source) {
|
||||
case Source::eAX:
|
||||
// Slightly contorted if chain here and below:
|
||||
@ -131,10 +103,63 @@ IntT *resolve(
|
||||
else if constexpr (std::is_same_v<IntT, uint8_t>) { return ®isters.bh(); }
|
||||
else { return nullptr; }
|
||||
|
||||
case Source::ES: if constexpr (std::is_same_v<IntT, uint16_t>) return ®isters.es(); else return nullptr;
|
||||
case Source::CS: if constexpr (std::is_same_v<IntT, uint16_t>) return ®isters.cs(); else return nullptr;
|
||||
case Source::SS: if constexpr (std::is_same_v<IntT, uint16_t>) return ®isters.ss(); else return nullptr;
|
||||
case Source::DS: if constexpr (std::is_same_v<IntT, uint16_t>) return ®isters.ds(); else return nullptr;
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <Model model, typename IntT, typename InstructionT, typename RegistersT, typename MemoryT>
|
||||
uint32_t address(
|
||||
InstructionT &instruction,
|
||||
DataPointer pointer,
|
||||
RegistersT ®isters,
|
||||
MemoryT &memory
|
||||
) {
|
||||
switch(pointer.source<false>()) {
|
||||
default: return 0;
|
||||
case Source::eAX: return *register_<model, IntT, Source::eAX>(registers);
|
||||
case Source::eCX: return *register_<model, IntT, Source::eCX>(registers);
|
||||
case Source::eDX: return *register_<model, IntT, Source::eDX>(registers);
|
||||
case Source::eBX: return *register_<model, IntT, Source::eBX>(registers);
|
||||
case Source::eSPorAH: return *register_<model, IntT, Source::eSPorAH>(registers);
|
||||
case Source::eBPorCH: return *register_<model, IntT, Source::eBPorCH>(registers);
|
||||
case Source::eSIorDH: return *register_<model, IntT, Source::eSIorDH>(registers);
|
||||
case Source::eDIorBH: return *register_<model, IntT, Source::eDIorBH>(registers);
|
||||
case Source::Indirect: return address<model, Source::Indirect, IntT>(instruction, pointer, registers, memory);
|
||||
case Source::IndirectNoBase: return address<model, Source::IndirectNoBase, IntT>(instruction, pointer, registers, memory);
|
||||
case Source::DirectAddress: return address<model, Source::DirectAddress, IntT>(instruction, pointer, registers, memory);
|
||||
}
|
||||
}
|
||||
|
||||
template <Model model, typename IntT, typename InstructionT, typename RegistersT, typename MemoryT>
|
||||
IntT *resolve(
|
||||
InstructionT &instruction,
|
||||
Source source,
|
||||
DataPointer pointer,
|
||||
RegistersT ®isters,
|
||||
MemoryT &memory,
|
||||
IntT *none,
|
||||
IntT *immediate
|
||||
) {
|
||||
// Rules:
|
||||
//
|
||||
// * if this is a memory access, set target_address and break;
|
||||
// * otherwise return the appropriate value.
|
||||
uint32_t target_address;
|
||||
switch(source) {
|
||||
case Source::eAX: return register_<model, IntT, Source::eAX>(registers);
|
||||
case Source::eCX: return register_<model, IntT, Source::eCX>(registers);
|
||||
case Source::eDX: return register_<model, IntT, Source::eDX>(registers);
|
||||
case Source::eBX: return register_<model, IntT, Source::eBX>(registers);
|
||||
case Source::eSPorAH: return register_<model, IntT, Source::eSPorAH>(registers);
|
||||
case Source::eBPorCH: return register_<model, IntT, Source::eBPorCH>(registers);
|
||||
case Source::eSIorDH: return register_<model, IntT, Source::eSIorDH>(registers);
|
||||
case Source::eDIorBH: return register_<model, IntT, Source::eDIorBH>(registers);
|
||||
|
||||
// Segment registers are always 16-bit.
|
||||
case Source::ES: if constexpr (std::is_same_v<IntT, uint16_t>) return ®isters.es(); else return nullptr;
|
||||
case Source::CS: if constexpr (std::is_same_v<IntT, uint16_t>) return ®isters.cs(); else return nullptr;
|
||||
case Source::SS: if constexpr (std::is_same_v<IntT, uint16_t>) return ®isters.ss(); else return nullptr;
|
||||
case Source::DS: if constexpr (std::is_same_v<IntT, uint16_t>) return ®isters.ds(); else return nullptr;
|
||||
|
||||
// 16-bit models don't have FS and GS.
|
||||
case Source::FS: if constexpr (is_32bit(model) && std::is_same_v<IntT, uint16_t>) return ®isters.fs(); else return nullptr;
|
||||
|
@ -25,7 +25,7 @@ namespace {
|
||||
|
||||
// The tests themselves are not duplicated in this repository;
|
||||
// provide their real path here.
|
||||
constexpr char TestSuiteHome[] = "/Users/tharte/Projects/ProcessorTests/8088/v1";
|
||||
constexpr char TestSuiteHome[] = "/Users/thomasharte/Projects/ProcessorTests/8088/v1";
|
||||
|
||||
using Status = InstructionSet::x86::Status;
|
||||
struct Registers {
|
||||
@ -497,6 +497,10 @@ struct FailedExecution {
|
||||
execution_support.status = initial_status;
|
||||
execution_support.registers = initial_registers;
|
||||
|
||||
if(decoded.second.operation != InstructionSet::x86::Operation::LEA) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute instruction.
|
||||
//
|
||||
// TODO: enquire of the actual mechanism of repetition; if it were stateful as below then
|
||||
|
Loading…
Reference in New Issue
Block a user