1
0
mirror of https://github.com/jborza/emu6502.git synced 2024-06-15 07:29:49 +00:00

PHA, PLA, TXS, TYS, TSX, TSY + tests

This commit is contained in:
jborza 2019-04-16 22:46:28 +02:00
parent ee71eae5e5
commit e6a8c7934c
4 changed files with 179 additions and 29 deletions

53
cpu.c
View File

@ -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
View File

@ -1,6 +1,8 @@
#pragma once
#include "types.h"
#define STACK_HOME 0x100
void* unimplemented_instruction(State6502* state);
int emulate_6502_op(State6502* state);

View File

@ -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));

View File

@ -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);
}