erc-c/src/mos6502/loadstor.c

200 lines
3.1 KiB
C

/*
* mos6502.loadstor.c
*
* These are all the instructions which load and store values into
* various registers and places in memory.
*/
#include "mos6502/mos6502.h"
#include "mos6502/enums.h"
/*
* The LDA instruction will assign ("load") an operand into the
* accumulator.
*/
DEFINE_INST(lda)
{
MOS_CHECK_NZ(oper);
cpu->A = oper;
}
/*
* Similar to LDA, except targeting X.
*/
DEFINE_INST(ldx)
{
MOS_CHECK_NZ(oper);
cpu->X = oper;
}
/*
* Again similar to LDA, except with Y.
*/
DEFINE_INST(ldy)
{
MOS_CHECK_NZ(oper);
cpu->Y = oper;
}
/*
* This instruction will "push" the A register onto the stack.
*/
DEFINE_INST(pha)
{
mos6502_push_stack(cpu, cpu->A);
}
/*
* Similar to above, but will push the P register.
*/
DEFINE_INST(php)
{
mos6502_push_stack(cpu, cpu->P);
}
/*
* Push the X register onto the stack. Sadly, this does not summon a
* phoenix to assist you in hours of need.
*/
DEFINE_INST(phx)
{
mos6502_push_stack(cpu, cpu->X);
}
/*
* Push the Y register onto the stack
*/
DEFINE_INST(phy)
{
mos6502_push_stack(cpu, cpu->Y);
}
/*
* Here we pop the stack (or "pull" it), and assign to the accumulator.
*/
DEFINE_INST(pla)
{
vm_8bit result = mos6502_pop_stack(cpu);
MOS_CHECK_NZ(result);
cpu->A = result;
}
/*
* Again we pop from the stack, but assign to the P register.
*/
DEFINE_INST(plp)
{
cpu->P = mos6502_pop_stack(cpu);
}
/*
* Pop from the stack and assign that byte to the X register
*/
DEFINE_INST(plx)
{
vm_8bit result = mos6502_pop_stack(cpu);
MOS_CHECK_NZ(result);
cpu->X = result;
}
/*
* Pop from the stack and assign that byte to the Y register
*/
DEFINE_INST(ply)
{
vm_8bit result = mos6502_pop_stack(cpu);
MOS_CHECK_NZ(result);
cpu->Y = result;
}
/*
* The STA instruction assigns the value of the accumulator to a given
* address in memory. (That is to say, it "stores" it.)
*/
DEFINE_INST(sta)
{
mos6502_set(cpu, cpu->eff_addr, cpu->A);
}
/*
* Similar to STA, but drawing from the X register.
*/
DEFINE_INST(stx)
{
mos6502_set(cpu, cpu->eff_addr, cpu->X);
}
/*
* And, again, similar to STA, but with the Y register.
*/
DEFINE_INST(sty)
{
mos6502_set(cpu, cpu->eff_addr, cpu->Y);
}
/*
* Store a zero byte into the effective address
*/
DEFINE_INST(stz)
{
mos6502_set(cpu, cpu->eff_addr, 0);
}
/*
* The TAX instruction taxes no one but your patience for my puns. What
* it does do is transfer the contents of the A register to X.
*/
DEFINE_INST(tax)
{
MOS_CHECK_NZ(cpu->A);
cpu->X = cpu->A;
}
/*
* This transfers from A to Y.
*/
DEFINE_INST(tay)
{
MOS_CHECK_NZ(cpu->A);
cpu->Y = cpu->A;
}
/*
* Transfer the stack pointer (S register) to X.
*/
DEFINE_INST(tsx)
{
MOS_CHECK_NZ(cpu->S);
cpu->X = cpu->S;
}
/*
* Transfer the X register to A.
*/
DEFINE_INST(txa)
{
MOS_CHECK_NZ(cpu->X);
cpu->A = cpu->X;
}
/*
* Transfer the X register to S.
*/
DEFINE_INST(txs)
{
MOS_CHECK_NZ(cpu->X);
cpu->S = cpu->X;
}
/*
* Transfer the Y register to A.
*/
DEFINE_INST(tya)
{
MOS_CHECK_NZ(cpu->Y);
cpu->A = cpu->Y;
}