1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Implement PUSHA, POPA.

This commit is contained in:
Thomas Harte 2023-11-14 10:42:06 -05:00
parent 1552500b10
commit 6c405680f2
2 changed files with 64 additions and 2 deletions

View File

@ -348,8 +348,11 @@ template <
Primitive::push<IntT, false>(source_rmw(), context); // PUSH SP modifies SP before pushing it; Primitive::push<IntT, false>(source_rmw(), context); // PUSH SP modifies SP before pushing it;
// hence PUSH is sometimes read-modify-write. // hence PUSH is sometimes read-modify-write.
break; break;
case Operation::POPF: Primitive::popf(context); return; case Operation::POPF: Primitive::popf(context); return;
case Operation::PUSHF: Primitive::pushf(context); return; case Operation::PUSHF: Primitive::pushf(context); return;
case Operation::POPA: Primitive::popa<IntT>(context); return;
case Operation::PUSHA: Primitive::pusha<IntT>(context); return;
case Operation::CMPS: case Operation::CMPS:
Primitive::cmps<IntT, AddressT, Repetition::None>(instruction, eCX(), eSI(), eDI(), context); Primitive::cmps<IntT, AddressT, Repetition::None>(instruction, eCX(), eSI(), eDI(), context);

View File

@ -11,6 +11,8 @@
#include "../AccessType.hpp" #include "../AccessType.hpp"
#include <type_traits>
namespace InstructionSet::x86::Primitive { namespace InstructionSet::x86::Primitive {
// The below takes a reference in order properly to handle PUSH SP, // The below takes a reference in order properly to handle PUSH SP,
@ -89,6 +91,63 @@ void pushf(
push<uint16_t, false>(value, context); push<uint16_t, false>(value, context);
} }
template <typename IntT, typename ContextT>
void popa(
ContextT &context
) {
if constexpr (!std::is_same_v<IntT, uint8_t>) {
context.memory.preauthorise_stack_read(sizeof(IntT) * 8);
if constexpr (std::is_same_v<IntT, uint32_t>) {
context.registers.edi() = pop<uint32_t, true>(context);
context.registers.esi() = pop<uint32_t, true>(context);
context.registers.ebp() = pop<uint32_t, true>(context);
context.registers.esp() += 4;
context.registers.ebx() = pop<uint32_t, true>(context);
context.registers.edx() = pop<uint32_t, true>(context);
context.registers.ecx() = pop<uint32_t, true>(context);
context.registers.eax() = pop<uint32_t, true>(context);
} else {
context.registers.di() = pop<uint16_t, true>(context);
context.registers.si() = pop<uint16_t, true>(context);
context.registers.bp() = pop<uint16_t, true>(context);
context.registers.sp() += 2;
context.registers.bx() = pop<uint16_t, true>(context);
context.registers.dx() = pop<uint16_t, true>(context);
context.registers.cx() = pop<uint16_t, true>(context);
context.registers.ax() = pop<uint16_t, true>(context);
}
}
}
template <typename IntT, typename ContextT>
void pusha(
ContextT &context
) {
if constexpr (!std::is_same_v<IntT, uint8_t>) {
context.memory.preauthorise_stack_read(sizeof(IntT) * 8);
IntT initial_sp = context.registers.sp();
if constexpr (std::is_same_v<IntT, uint32_t>) {
push<uint32_t, true>(context.registers.eax(), context);
push<uint32_t, true>(context.registers.ecx(), context);
push<uint32_t, true>(context.registers.edx(), context);
push<uint32_t, true>(context.registers.ebx(), context);
push<uint32_t, true>(initial_sp, context);
push<uint32_t, true>(context.registers.ebp(), context);
push<uint32_t, true>(context.registers.esi(), context);
push<uint32_t, true>(context.registers.esi(), context);
} else {
push<uint16_t, true>(context.registers.ax(), context);
push<uint16_t, true>(context.registers.cx(), context);
push<uint16_t, true>(context.registers.dx(), context);
push<uint16_t, true>(context.registers.bx(), context);
push<uint16_t, true>(initial_sp, context);
push<uint16_t, true>(context.registers.bp(), context);
push<uint16_t, true>(context.registers.si(), context);
push<uint16_t, true>(context.registers.si(), context);
}
}
}
} }
#endif /* Stack_hpp */ #endif /* Stack_hpp */