mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Slim down the flow controller.
This commit is contained in:
parent
097b328075
commit
bc095bb9ce
@ -821,14 +821,16 @@ void not_(IntT &destination) {
|
||||
destination = ~destination;
|
||||
}
|
||||
|
||||
template <typename IntT, typename RegistersT, typename FlowControllerT>
|
||||
void call_relative(IntT offset, RegistersT ®isters, FlowControllerT &flow_controller) {
|
||||
flow_controller.call(registers.ip() + offset);
|
||||
template <typename IntT, typename RegistersT, typename MemoryT, typename FlowControllerT>
|
||||
void call_relative(IntT offset, RegistersT ®isters, MemoryT &memory, FlowControllerT &flow_controller) {
|
||||
push<uint16_t, false>(registers.ip(), memory, registers);
|
||||
flow_controller.jump(registers.ip() + offset);
|
||||
}
|
||||
|
||||
template <typename IntT, typename FlowControllerT>
|
||||
void call_absolute(IntT target, FlowControllerT &flow_controller) {
|
||||
flow_controller.call(target);
|
||||
template <typename IntT, typename RegistersT, typename MemoryT, typename FlowControllerT>
|
||||
void call_absolute(IntT target, RegistersT ®isters, MemoryT &memory, FlowControllerT &flow_controller) {
|
||||
push<uint16_t, false>(registers.ip(), memory, registers);
|
||||
flow_controller.jump(target);
|
||||
}
|
||||
|
||||
template <typename IntT, typename FlowControllerT>
|
||||
@ -843,11 +845,18 @@ void call_far(InstructionT &instruction,
|
||||
MemoryT &memory
|
||||
) {
|
||||
// TODO: eliminate 16-bit assumption below.
|
||||
uint16_t source_address = 0;
|
||||
const Source source_segment = instruction.data_segment();
|
||||
memory.preauthorise_stack_write(sizeof(uint16_t) * 2);
|
||||
|
||||
uint16_t source_address;
|
||||
const auto pointer = instruction.destination();
|
||||
switch(pointer.source()) {
|
||||
default:
|
||||
case Source::Immediate: flow_controller.call(instruction.segment(), instruction.offset()); return;
|
||||
case Source::Immediate:
|
||||
push<uint16_t, true>(registers.cs(), memory, registers);
|
||||
push<uint16_t, true>(registers.ip(), memory, registers);
|
||||
flow_controller.jump(instruction.segment(), instruction.offset());
|
||||
return;
|
||||
|
||||
case Source::Indirect:
|
||||
source_address = address<model, Source::Indirect, uint16_t, AccessType::Read>(instruction, pointer, registers, memory);
|
||||
@ -860,13 +869,14 @@ void call_far(InstructionT &instruction,
|
||||
break;
|
||||
}
|
||||
|
||||
const Source source_segment = instruction.data_segment();
|
||||
memory.preauthorise_read(source_segment, source_address, sizeof(uint16_t) * 2);
|
||||
push<uint16_t, true>(registers.cs(), memory, registers);
|
||||
push<uint16_t, true>(registers.ip(), memory, registers);
|
||||
|
||||
// TODO: preauthorise reads.
|
||||
const uint16_t offset = memory.template access<uint16_t, AccessType::Read>(source_segment, source_address);
|
||||
const uint16_t offset = memory.template access<uint16_t, AccessType::PreauthorisedRead>(source_segment, source_address);
|
||||
source_address += 2;
|
||||
const uint16_t segment = memory.template access<uint16_t, AccessType::Read>(source_segment, source_address);
|
||||
flow_controller.call(segment, offset);
|
||||
const uint16_t segment = memory.template access<uint16_t, AccessType::PreauthorisedRead>(source_segment, source_address);
|
||||
flow_controller.jump(segment, offset);
|
||||
}
|
||||
|
||||
template <Model model, typename InstructionT, typename FlowControllerT, typename RegistersT, typename MemoryT>
|
||||
@ -904,27 +914,27 @@ void jump_far(InstructionT &instruction,
|
||||
template <typename FlowControllerT, typename RegistersT, typename MemoryT>
|
||||
void iret(RegistersT ®isters, FlowControllerT &flow_controller, MemoryT &memory, Status &status) {
|
||||
// TODO: all modes other than 16-bit real mode.
|
||||
memory.preauthorise_stack(sizeof(uint16_t) * 3);
|
||||
registers.ip() = pop<uint16_t, true>(memory, registers);
|
||||
registers.cs() = pop<uint16_t, true>(memory, registers);
|
||||
memory.preauthorise_stack_read(sizeof(uint16_t) * 3);
|
||||
const auto ip = pop<uint16_t, true>(memory, registers);
|
||||
const auto cs = pop<uint16_t, true>(memory, registers);
|
||||
status.set(pop<uint16_t, true>(memory, registers));
|
||||
flow_controller.did_iret();
|
||||
flow_controller.jump(cs, ip);
|
||||
}
|
||||
|
||||
template <typename InstructionT, typename FlowControllerT, typename RegistersT, typename MemoryT>
|
||||
void ret_near(InstructionT instruction, RegistersT ®isters, FlowControllerT &flow_controller, MemoryT &memory) {
|
||||
registers.ip() = pop<uint16_t, false>(memory, registers);
|
||||
const auto ip = pop<uint16_t, false>(memory, registers);
|
||||
registers.sp() += instruction.operand();
|
||||
flow_controller.did_near_ret();
|
||||
flow_controller.jump(ip);
|
||||
}
|
||||
|
||||
template <typename InstructionT, typename FlowControllerT, typename RegistersT, typename MemoryT>
|
||||
void ret_far(InstructionT instruction, RegistersT ®isters, FlowControllerT &flow_controller, MemoryT &memory) {
|
||||
memory.preauthorise_stack(sizeof(uint16_t) * 2);
|
||||
registers.ip() = pop<uint16_t, true>(memory, registers);
|
||||
registers.cs() = pop<uint16_t, true>(memory, registers);
|
||||
memory.preauthorise_stack_read(sizeof(uint16_t) * 2);
|
||||
const auto ip = pop<uint16_t, true>(memory, registers);
|
||||
const auto cs = pop<uint16_t, true>(memory, registers);
|
||||
registers.sp() += instruction.operand();
|
||||
flow_controller.did_far_ret();
|
||||
flow_controller.jump(cs, ip);
|
||||
}
|
||||
|
||||
template <Model model, Source selector, typename InstructionT, typename MemoryT, typename RegistersT>
|
||||
@ -1691,10 +1701,10 @@ template <
|
||||
case Operation::NOT: Primitive::not_(source_rmw()); break; // TODO: should be a destination.
|
||||
|
||||
case Operation::CALLrel:
|
||||
Primitive::call_relative(instruction.displacement(), registers, flow_controller);
|
||||
Primitive::call_relative(instruction.displacement(), registers, memory, flow_controller);
|
||||
return;
|
||||
case Operation::CALLabs:
|
||||
Primitive::call_absolute(destination_r(), flow_controller);
|
||||
Primitive::call_absolute(destination_r(), registers, memory, flow_controller);
|
||||
return;
|
||||
case Operation::CALLfar:
|
||||
Primitive::call_far<model>(instruction, flow_controller, registers, memory);
|
||||
|
@ -133,7 +133,9 @@ struct Memory {
|
||||
return physical_address << 4;
|
||||
}
|
||||
|
||||
void preauthorise_stack(uint32_t) {}
|
||||
void preauthorise_stack_write(uint32_t) {}
|
||||
void preauthorise_stack_read(uint32_t) {}
|
||||
void preauthorise_read(InstructionSet::x86::Source, uint16_t, uint32_t) {}
|
||||
|
||||
// Entry point used by the flow controller so that it can mark up locations at which the flags were written,
|
||||
// so that defined-flag-only masks can be applied while verifying RAM contents.
|
||||
@ -233,10 +235,6 @@ class FlowController {
|
||||
FlowController(Memory &memory, Registers ®isters, Status &status) :
|
||||
memory_(memory), registers_(registers), status_(status) {}
|
||||
|
||||
void did_iret() {}
|
||||
void did_near_ret() {}
|
||||
void did_far_ret() {}
|
||||
|
||||
void interrupt(int index) {
|
||||
// TODO: reauthorise and possibly double fault?
|
||||
const uint16_t address = static_cast<uint16_t>(index) << 2;
|
||||
@ -256,17 +254,6 @@ class FlowController {
|
||||
registers_.ip_ = new_ip;
|
||||
}
|
||||
|
||||
void call(uint16_t address) {
|
||||
push(registers_.ip_);
|
||||
jump(address);
|
||||
}
|
||||
|
||||
void call(uint16_t segment, uint16_t offset) {
|
||||
push(registers_.cs_);
|
||||
push(registers_.ip_);
|
||||
jump(segment, offset);
|
||||
}
|
||||
|
||||
void jump(uint16_t address) {
|
||||
registers_.ip_ = address;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user