mirror of
https://github.com/jborza/emu6502.git
synced 2025-02-19 07:30:57 +00:00
PHA, PLA, TXS, TYS, TSX, TSY + tests
This commit is contained in:
parent
ee71eae5e5
commit
e6a8c7934c
53
cpu.c
53
cpu.c
@ -24,13 +24,19 @@ void set_NZ_flags(State6502 * state, byte value) {
|
||||
else {
|
||||
state->flags.z = 1;
|
||||
}
|
||||
printf("setting z flag to %d\n", state->flags.z);
|
||||
//N flag
|
||||
state->flags.n = ((1 << 7) & value) != 0;
|
||||
}
|
||||
|
||||
void clear_flags(State6502 * state) {
|
||||
memcpy(&state->flags, &state->a, 1);
|
||||
state->flags.b =
|
||||
state->flags.c =
|
||||
state->flags.d =
|
||||
state->flags.i =
|
||||
state->flags.n =
|
||||
state->flags.v =
|
||||
state->flags.z = 0;
|
||||
state->flags.pad = 1; //unused is supposed to be 1
|
||||
}
|
||||
|
||||
void clear_state(State6502 * state) {
|
||||
@ -47,6 +53,16 @@ byte pop_byte(State6502 * state) {
|
||||
return state->memory[state->pc++];
|
||||
}
|
||||
|
||||
void push_byte_to_stack(State6502 * state, byte value) {
|
||||
//stack located between $0100 to $01FF
|
||||
state->memory[STACK_HOME + state->sp--] = value;
|
||||
}
|
||||
|
||||
byte pop_byte_from_stack(State6502 * state) {
|
||||
return state->memory[STACK_HOME + state->sp++];
|
||||
state->sp++;
|
||||
}
|
||||
|
||||
//bitwise or with accumulator
|
||||
void ORA(State6502 * state, byte operand) {
|
||||
byte result = state->a | operand;
|
||||
@ -246,25 +262,30 @@ int emulate_6502_op(State6502 * state) {
|
||||
case CLI: state->flags.i = 0; break;
|
||||
case CLV: state->flags.v = 0; break;
|
||||
case NOP: break; //NOP
|
||||
case PHA: unimplemented_instruction(state); break;
|
||||
case PLA: unimplemented_instruction(state); break;
|
||||
case PHP: //push processor status
|
||||
//push(state->flags);
|
||||
unimplemented_instruction(state); break;
|
||||
case PLP: //pull procesor status
|
||||
//state->flags = pop();
|
||||
unimplemented_instruction(state); break;
|
||||
case PHA: push_byte_to_stack(state, state->a); break; //push accumulator to stack
|
||||
case PLA: state->a = pop_byte_from_stack(state); break; //pull accumulator from stack
|
||||
case PHP: {
|
||||
byte flags_value;
|
||||
memcpy(&flags_value, &state->flags, sizeof(Flags));
|
||||
push_byte_to_stack(state, flags_value);
|
||||
break; //push processor status
|
||||
}
|
||||
case PLP: {
|
||||
byte value = pop_byte_from_stack(state);
|
||||
memset(&state->flags, value, 1);
|
||||
break;
|
||||
}//pull procesor status
|
||||
case RTI: unimplemented_instruction(state); break;
|
||||
case RTS: unimplemented_instruction(state); break;
|
||||
case SEC: state->flags.c = 1; break;
|
||||
case SED: state->flags.d = 1; break;
|
||||
case SEI: state->flags.i = 1; break;
|
||||
case TAX: state->x = state->a; set_NZ_flags(state, state->x); break; //TODO test
|
||||
case TXA: state->a = state->x; set_NZ_flags(state, state->a); break; //TODO test
|
||||
case TAY: state->y = state->a; set_NZ_flags(state, state->y); break; //TODO test
|
||||
case TYA: state->a = state->y; set_NZ_flags(state, state->a); break; //TODO test
|
||||
case TSX: unimplemented_instruction(state); break;
|
||||
case TXS: unimplemented_instruction(state); break;
|
||||
case TAX: state->x = state->a; set_NZ_flags(state, state->x); break;
|
||||
case TXA: state->a = state->x; set_NZ_flags(state, state->a); break;
|
||||
case TAY: state->y = state->a; set_NZ_flags(state, state->y); break;
|
||||
case TYA: state->a = state->y; set_NZ_flags(state, state->a); break;
|
||||
case TSX: state->x = state->sp; set_NZ_flags(state, state->x); break; //TODO test
|
||||
case TXS: state->sp = state->x; set_NZ_flags(state, state->x); break; //TODO test
|
||||
case CMP_IMM: unimplemented_instruction(state); break;
|
||||
case CMP_ZP: unimplemented_instruction(state); break;
|
||||
case CMP_ZPX: unimplemented_instruction(state); break;
|
||||
|
2
cpu.h
2
cpu.h
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
#define STACK_HOME 0x100
|
||||
|
||||
void* unimplemented_instruction(State6502* state);
|
||||
int emulate_6502_op(State6502* state);
|
||||
|
||||
|
@ -25,6 +25,11 @@ int main()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void emulate_game() {
|
||||
FILE* file = fopen("..\\bins\\tetris.bin", "r");
|
||||
|
||||
}
|
||||
|
||||
//void emulate() {
|
||||
// State6502 state;
|
||||
// memset(&state.memory, 0, sizeof(State6502));
|
||||
|
148
test6502.c
148
test6502.c
@ -54,25 +54,27 @@ State6502 create_blank_state() {
|
||||
return state;
|
||||
}
|
||||
|
||||
void assertA(State6502 * state, byte expected) {
|
||||
if (state->a != expected) {
|
||||
printf("Unexpected value in A, expected %02X, was %02X", expected, state->a);
|
||||
void assert_register(State6502* state, byte expected, byte actual, char* name) {
|
||||
if (actual != expected) {
|
||||
printf("Unexpected value in %s, expected %02X, was %02X", name, expected, actual);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void assertA(State6502 * state, byte expected) {
|
||||
assert_register(state, expected, state->a, "A");
|
||||
}
|
||||
|
||||
void assertX(State6502 * state, byte expected) {
|
||||
if (state->x != expected) {
|
||||
printf("Unexpected value in X, expected %02X, was %02X", expected, state->x);
|
||||
exit(1);
|
||||
}
|
||||
assert_register(state, expected, state->x, "X");
|
||||
}
|
||||
|
||||
void assertY(State6502 * state, byte expected) {
|
||||
if (state->y != expected) {
|
||||
printf("Unexpected value in X, expected %02X, was %02X", expected, state->y);
|
||||
exit(1);
|
||||
}
|
||||
assert_register(state, expected, state->y, "Y");
|
||||
}
|
||||
|
||||
void assert_sp(State6502* state, byte expected) {
|
||||
assert_register(state, expected, state->sp, "SP");
|
||||
}
|
||||
|
||||
//assert_memory(&state, 0xFF, 0x99)
|
||||
@ -1519,8 +1521,6 @@ void test_CLV() {
|
||||
|
||||
//// STA
|
||||
|
||||
//// STX
|
||||
|
||||
void test_STA_ZP() {
|
||||
//initialize
|
||||
State6502 state = create_blank_state();
|
||||
@ -1663,6 +1663,124 @@ void test_STA_INDY() {
|
||||
test_cleanup(&state);
|
||||
}
|
||||
|
||||
// PH, PL
|
||||
|
||||
void test_PHA() {
|
||||
//initialize
|
||||
State6502 state = create_blank_state();
|
||||
state.a = 0x99;
|
||||
state.sp = 0xFF;
|
||||
|
||||
//arrange
|
||||
char program[] = { PHA };
|
||||
memcpy(state.memory, program, sizeof(program));
|
||||
|
||||
//act
|
||||
test_step(&state);
|
||||
|
||||
//assert
|
||||
assert_memory(&state, 0x1FF, 0x99);
|
||||
assert_sp(&state, 0xFE);
|
||||
|
||||
//cleanup
|
||||
test_cleanup(&state);
|
||||
}
|
||||
|
||||
void test_PLA() {
|
||||
//initialize
|
||||
State6502 state = create_blank_state();
|
||||
state.sp = 0xFE;
|
||||
state.memory[0x1FE] = 0xBB;
|
||||
|
||||
//arrange
|
||||
char program[] = { PLA };
|
||||
memcpy(state.memory, program, sizeof(program));
|
||||
|
||||
//act
|
||||
test_step(&state);
|
||||
|
||||
//assert
|
||||
assertA(&state, 0xBB);
|
||||
assert_sp(&state, 0xFF);
|
||||
|
||||
//cleanup
|
||||
test_cleanup(&state);
|
||||
}
|
||||
|
||||
void test_PHA_PLA() {
|
||||
//initialize
|
||||
State6502 state = create_blank_state();
|
||||
|
||||
//arrange
|
||||
char program[] = { LDX_IMM, 0xFF, TXS, LDA_IMM, 0xAA, PHA, LDY_IMM, 0xBB, TYA, PHA, TXA, PHA };
|
||||
memcpy(state.memory, program, sizeof(program));
|
||||
|
||||
//act
|
||||
for (int i = 0; i < 9; i++) {
|
||||
disassemble_6502(state.memory, state.pc);
|
||||
emulate_6502_op(&state);
|
||||
}
|
||||
|
||||
//assert
|
||||
assert_memory(&state, 0x1FF, 0xAA);
|
||||
assert_memory(&state, 0x1FE, 0xBB);
|
||||
assert_memory(&state, 0x1FD, 0xFF);
|
||||
assert_sp(&state, 0xFC);
|
||||
|
||||
//cleanup
|
||||
test_cleanup(&state);
|
||||
}
|
||||
|
||||
//// TXS, TSX, TYS, TSY
|
||||
|
||||
void test_TXS() {
|
||||
State6502 state = create_blank_state();
|
||||
state.x = 0xAA;
|
||||
char program[] = { TXS };
|
||||
memcpy(state.memory, program, sizeof(program));
|
||||
test_step(&state);
|
||||
|
||||
assert_sp(&state, 0xAA);
|
||||
|
||||
test_cleanup(&state);
|
||||
}
|
||||
|
||||
void test_TSX() {
|
||||
State6502 state = create_blank_state();
|
||||
state.sp = 0xBB;
|
||||
char program[] = { TSX };
|
||||
memcpy(state.memory, program, sizeof(program));
|
||||
test_step(&state);
|
||||
|
||||
assertX(&state, 0xBB);
|
||||
|
||||
test_cleanup(&state);
|
||||
}
|
||||
|
||||
void test_TYS() {
|
||||
State6502 state = create_blank_state();
|
||||
state.y = 0xAA;
|
||||
char program[] = { TYS };
|
||||
memcpy(state.memory, program, sizeof(program));
|
||||
test_step(&state);
|
||||
|
||||
assert_sp(&state, 0xAA);
|
||||
|
||||
test_cleanup(&state);
|
||||
}
|
||||
|
||||
void test_TSY() {
|
||||
State6502 state = create_blank_state();
|
||||
state.sp = 0xBB;
|
||||
char program[] = { TSY };
|
||||
memcpy(state.memory, program, sizeof(program));
|
||||
test_step(&state);
|
||||
|
||||
assertY(&state, 0xBB);
|
||||
|
||||
test_cleanup(&state);
|
||||
}
|
||||
|
||||
/////////////////////
|
||||
|
||||
typedef void fp();
|
||||
@ -1679,6 +1797,8 @@ fp* tests_inc_dec[] = { test_INC_ZP, test_INC_ZP_wraparound, test_INC_ZPX, test_
|
||||
fp* tests_flags[] = { test_CLC, test_SEC, test_CLD, test_SED, test_SEI, test_CLI, test_CLV };
|
||||
fp* tests_eor[] = { test_EOR_IMM, test_EOR_ZP, test_EOR_ZPX, test_EOR_ABS, test_EOR_ABSX, test_EOR_ABSY, test_EOR_INDX, test_EOR_INDY };
|
||||
fp* tests_sta[] = { test_STA_ZP, test_STA_ZPX, test_STA_ABS, test_STA_ABSX, test_STA_ABSY, test_STA_INDX, test_STA_INDY };
|
||||
fp* tests_pha_pla[] = { test_PHA, test_PLA, test_PHA_PLA };
|
||||
fp* tests_txs_etc[] = { test_TXS, test_TSX, test_TYS, test_TSY };
|
||||
|
||||
#define RUN(suite) run_suite(suite, sizeof(suite)/sizeof(fp*))
|
||||
|
||||
@ -1702,4 +1822,6 @@ void run_tests() {
|
||||
RUN(tests_flags);
|
||||
RUN(tests_eor);
|
||||
RUN(tests_sta);
|
||||
RUN(tests_pha_pla);
|
||||
RUN(tests_txs_tsx);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user