// // Stack.hpp // Clock Signal // // Created by Thomas Harte on 08/11/2023. // Copyright © 2023 Thomas Harte. All rights reserved. // #ifndef Stack_hpp #define Stack_hpp #include "../AccessType.hpp" #include namespace InstructionSet::x86::Primitive { // The below takes a reference in order properly to handle PUSH SP, // which should place the value of SP after the push onto the stack. template void push( IntT &value, ContextT &context ) { context.registers.sp_ -= sizeof(IntT); if constexpr (preauthorised) { context.memory.template preauthorised_write(Source::SS, context.registers.sp_, value); } else { context.memory.template access( Source::SS, context.registers.sp_) = value; } context.memory.template write_back(); } template IntT pop( ContextT &context ) { const auto value = context.memory.template access( Source::SS, context.registers.sp_); context.registers.sp_ += sizeof(IntT); return value; } template void sahf( uint8_t &ah, ContextT &context ) { /* EFLAGS(SF:ZF:0:AF:0:PF:1:CF) ← AH; */ context.flags.template set_from(ah); context.flags.template set_from(!(ah & 0x40)); context.flags.template set_from(ah & 0x10); context.flags.template set_from(!(ah & 0x04)); context.flags.template set_from(ah & 0x01); } template void lahf( uint8_t &ah, ContextT &context ) { /* AH ← EFLAGS(SF:ZF:0:AF:0:PF:1:CF); */ ah = (context.flags.template flag() ? 0x80 : 0x00) | (context.flags.template flag() ? 0x40 : 0x00) | (context.flags.template flag() ? 0x10 : 0x00) | (context.flags.template flag() ? 0x00 : 0x04) | 0x02 | (context.flags.template flag() ? 0x01 : 0x00); } template void popf( ContextT &context ) { context.flags.set(pop(context)); } template void pushf( ContextT &context ) { uint16_t value = context.flags.get(); 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 */