diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index a0a1fe684..999aafe3f 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -348,8 +348,11 @@ template < Primitive::push(source_rmw(), context); // PUSH SP modifies SP before pushing it; // hence PUSH is sometimes read-modify-write. break; - case Operation::POPF: Primitive::popf(context); return; - case Operation::PUSHF: Primitive::pushf(context); return; + + case Operation::POPF: Primitive::popf(context); return; + case Operation::PUSHF: Primitive::pushf(context); return; + case Operation::POPA: Primitive::popa(context); return; + case Operation::PUSHA: Primitive::pusha(context); return; case Operation::CMPS: Primitive::cmps(instruction, eCX(), eSI(), eDI(), context); diff --git a/InstructionSets/x86/Implementation/Stack.hpp b/InstructionSets/x86/Implementation/Stack.hpp index b24619a15..d3d44dbc2 100644 --- a/InstructionSets/x86/Implementation/Stack.hpp +++ b/InstructionSets/x86/Implementation/Stack.hpp @@ -11,6 +11,8 @@ #include "../AccessType.hpp" +#include + namespace InstructionSet::x86::Primitive { // The below takes a reference in order properly to handle PUSH SP, @@ -89,6 +91,63 @@ void pushf( push(value, context); } +template +void popa( + ContextT &context +) { + if constexpr (!std::is_same_v) { + context.memory.preauthorise_stack_read(sizeof(IntT) * 8); + if constexpr (std::is_same_v) { + context.registers.edi() = pop(context); + context.registers.esi() = pop(context); + context.registers.ebp() = pop(context); + context.registers.esp() += 4; + context.registers.ebx() = pop(context); + context.registers.edx() = pop(context); + context.registers.ecx() = pop(context); + context.registers.eax() = pop(context); + } else { + context.registers.di() = pop(context); + context.registers.si() = pop(context); + context.registers.bp() = pop(context); + context.registers.sp() += 2; + context.registers.bx() = pop(context); + context.registers.dx() = pop(context); + context.registers.cx() = pop(context); + context.registers.ax() = pop(context); + } + } +} + +template +void pusha( + ContextT &context +) { + if constexpr (!std::is_same_v) { + context.memory.preauthorise_stack_read(sizeof(IntT) * 8); + IntT initial_sp = context.registers.sp(); + if constexpr (std::is_same_v) { + push(context.registers.eax(), context); + push(context.registers.ecx(), context); + push(context.registers.edx(), context); + push(context.registers.ebx(), context); + push(initial_sp, context); + push(context.registers.ebp(), context); + push(context.registers.esi(), context); + push(context.registers.esi(), context); + } else { + push(context.registers.ax(), context); + push(context.registers.cx(), context); + push(context.registers.dx(), context); + push(context.registers.bx(), context); + push(initial_sp, context); + push(context.registers.bp(), context); + push(context.registers.si(), context); + push(context.registers.si(), context); + } + } +} + } #endif /* Stack_hpp */