mirror of
https://github.com/jborza/emu6502.git
synced 2025-02-21 06:29:03 +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 {
|
else {
|
||||||
state->flags.z = 1;
|
state->flags.z = 1;
|
||||||
}
|
}
|
||||||
printf("setting z flag to %d\n", state->flags.z);
|
|
||||||
//N flag
|
//N flag
|
||||||
state->flags.n = ((1 << 7) & value) != 0;
|
state->flags.n = ((1 << 7) & value) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_flags(State6502 * state) {
|
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) {
|
void clear_state(State6502 * state) {
|
||||||
@ -47,6 +53,16 @@ byte pop_byte(State6502 * state) {
|
|||||||
return state->memory[state->pc++];
|
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
|
//bitwise or with accumulator
|
||||||
void ORA(State6502 * state, byte operand) {
|
void ORA(State6502 * state, byte operand) {
|
||||||
byte result = state->a | operand;
|
byte result = state->a | operand;
|
||||||
@ -246,25 +262,30 @@ int emulate_6502_op(State6502 * state) {
|
|||||||
case CLI: state->flags.i = 0; break;
|
case CLI: state->flags.i = 0; break;
|
||||||
case CLV: state->flags.v = 0; break;
|
case CLV: state->flags.v = 0; break;
|
||||||
case NOP: break; //NOP
|
case NOP: break; //NOP
|
||||||
case PHA: unimplemented_instruction(state); break;
|
case PHA: push_byte_to_stack(state, state->a); break; //push accumulator to stack
|
||||||
case PLA: unimplemented_instruction(state); break;
|
case PLA: state->a = pop_byte_from_stack(state); break; //pull accumulator from stack
|
||||||
case PHP: //push processor status
|
case PHP: {
|
||||||
//push(state->flags);
|
byte flags_value;
|
||||||
unimplemented_instruction(state); break;
|
memcpy(&flags_value, &state->flags, sizeof(Flags));
|
||||||
case PLP: //pull procesor status
|
push_byte_to_stack(state, flags_value);
|
||||||
//state->flags = pop();
|
break; //push processor status
|
||||||
unimplemented_instruction(state); break;
|
}
|
||||||
|
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 RTI: unimplemented_instruction(state); break;
|
||||||
case RTS: unimplemented_instruction(state); break;
|
case RTS: unimplemented_instruction(state); break;
|
||||||
case SEC: state->flags.c = 1; break;
|
case SEC: state->flags.c = 1; break;
|
||||||
case SED: state->flags.d = 1; break;
|
case SED: state->flags.d = 1; break;
|
||||||
case SEI: state->flags.i = 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 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; //TODO test
|
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; //TODO test
|
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; //TODO test
|
case TYA: state->a = state->y; set_NZ_flags(state, state->a); break;
|
||||||
case TSX: unimplemented_instruction(state); break;
|
case TSX: state->x = state->sp; set_NZ_flags(state, state->x); break; //TODO test
|
||||||
case TXS: unimplemented_instruction(state); break;
|
case TXS: state->sp = state->x; set_NZ_flags(state, state->x); break; //TODO test
|
||||||
case CMP_IMM: unimplemented_instruction(state); break;
|
case CMP_IMM: unimplemented_instruction(state); break;
|
||||||
case CMP_ZP: unimplemented_instruction(state); break;
|
case CMP_ZP: unimplemented_instruction(state); break;
|
||||||
case CMP_ZPX: unimplemented_instruction(state); break;
|
case CMP_ZPX: unimplemented_instruction(state); break;
|
||||||
|
2
cpu.h
2
cpu.h
@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
#define STACK_HOME 0x100
|
||||||
|
|
||||||
void* unimplemented_instruction(State6502* state);
|
void* unimplemented_instruction(State6502* state);
|
||||||
int emulate_6502_op(State6502* state);
|
int emulate_6502_op(State6502* state);
|
||||||
|
|
||||||
|
@ -25,6 +25,11 @@ int main()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void emulate_game() {
|
||||||
|
FILE* file = fopen("..\\bins\\tetris.bin", "r");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//void emulate() {
|
//void emulate() {
|
||||||
// State6502 state;
|
// State6502 state;
|
||||||
// memset(&state.memory, 0, sizeof(State6502));
|
// memset(&state.memory, 0, sizeof(State6502));
|
||||||
|
148
test6502.c
148
test6502.c
@ -54,25 +54,27 @@ State6502 create_blank_state() {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void assertA(State6502 * state, byte expected) {
|
void assert_register(State6502* state, byte expected, byte actual, char* name) {
|
||||||
if (state->a != expected) {
|
if (actual != expected) {
|
||||||
printf("Unexpected value in A, expected %02X, was %02X", expected, state->a);
|
printf("Unexpected value in %s, expected %02X, was %02X", name, expected, actual);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void assertA(State6502 * state, byte expected) {
|
||||||
|
assert_register(state, expected, state->a, "A");
|
||||||
|
}
|
||||||
|
|
||||||
void assertX(State6502 * state, byte expected) {
|
void assertX(State6502 * state, byte expected) {
|
||||||
if (state->x != expected) {
|
assert_register(state, expected, state->x, "X");
|
||||||
printf("Unexpected value in X, expected %02X, was %02X", expected, state->x);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void assertY(State6502 * state, byte expected) {
|
void assertY(State6502 * state, byte expected) {
|
||||||
if (state->y != expected) {
|
assert_register(state, expected, state->y, "Y");
|
||||||
printf("Unexpected value in X, expected %02X, was %02X", expected, state->y);
|
}
|
||||||
exit(1);
|
|
||||||
}
|
void assert_sp(State6502* state, byte expected) {
|
||||||
|
assert_register(state, expected, state->sp, "SP");
|
||||||
}
|
}
|
||||||
|
|
||||||
//assert_memory(&state, 0xFF, 0x99)
|
//assert_memory(&state, 0xFF, 0x99)
|
||||||
@ -1519,8 +1521,6 @@ void test_CLV() {
|
|||||||
|
|
||||||
//// STA
|
//// STA
|
||||||
|
|
||||||
//// STX
|
|
||||||
|
|
||||||
void test_STA_ZP() {
|
void test_STA_ZP() {
|
||||||
//initialize
|
//initialize
|
||||||
State6502 state = create_blank_state();
|
State6502 state = create_blank_state();
|
||||||
@ -1663,6 +1663,124 @@ void test_STA_INDY() {
|
|||||||
test_cleanup(&state);
|
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();
|
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_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_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_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*))
|
#define RUN(suite) run_suite(suite, sizeof(suite)/sizeof(fp*))
|
||||||
|
|
||||||
@ -1702,4 +1822,6 @@ void run_tests() {
|
|||||||
RUN(tests_flags);
|
RUN(tests_flags);
|
||||||
RUN(tests_eor);
|
RUN(tests_eor);
|
||||||
RUN(tests_sta);
|
RUN(tests_sta);
|
||||||
|
RUN(tests_pha_pla);
|
||||||
|
RUN(tests_txs_tsx);
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user