1
0
mirror of https://github.com/jborza/emu6502.git synced 2024-11-21 23:31:19 +00:00

fixed PHP flag handling + test

This commit is contained in:
jborza 2019-05-04 14:11:39 +02:00
parent 8754aaef9f
commit 836a076d1c
4 changed files with 73 additions and 36 deletions

16
cpu.c
View File

@ -31,8 +31,17 @@ void set_NZ_flags(State6502 * state, byte value) {
} }
byte flags_as_byte(State6502 * state) { byte flags_as_byte(State6502 * state) {
byte flags_value; byte flags_value = 0;
memcpy(&flags_value, &state->flags, sizeof(Flags)); flags_value |= state->flags.c << 0;
flags_value |= state->flags.z << 1;
flags_value |= state->flags.i << 2;
flags_value |= state->flags.d << 3;
//flag B is active with PHP
flags_value |= 1 << 4;
//unused bit is active with PHP
flags_value |= 1 << 5;
flags_value |= state->flags.v << 6;
flags_value |= state->flags.n << 7;
return flags_value; return flags_value;
} }
@ -350,8 +359,7 @@ void PLP_(State6502* state) {
} }
void PHP_(State6502 * state) { void PHP_(State6502 * state) {
byte flags_value; byte flags_value = flags_as_byte(state);
memcpy(&flags_value, &state->flags, sizeof(Flags));
push_byte_to_stack(state, flags_value); push_byte_to_stack(state, flags_value);
} }

View File

@ -22,12 +22,18 @@ byte* read_nestest() {
int err = errno; int err = errno;
exit(1); exit(1);
} }
byte buffer[NESTEST_SIZE]; static byte buffer[NESTEST_SIZE];
int read = fread(&buffer, sizeof(byte), NESTEST_SIZE, file); int read = fread(&buffer, sizeof(byte), NESTEST_SIZE, file);
fclose(file); fclose(file);
return buffer; return buffer;
} }
byte debug_flags_as_byte(State6502* state) {
byte flags_value = 0;
memcpy(&flags_value, &state->flags, sizeof(Flags));
return flags_value;
}
void run_nestest() { void run_nestest() {
State6502 state; State6502 state;
clear_state(&state); clear_state(&state);
@ -38,16 +44,19 @@ void run_nestest() {
memcpy(state.memory + NESTEST_DST, bin, NESTEST_SIZE); memcpy(state.memory + NESTEST_DST, bin, NESTEST_SIZE);
memcpy(state.memory + 0x8000, bin, NESTEST_SIZE); memcpy(state.memory + 0x8000, bin, NESTEST_SIZE);
state.pc = NESTEST_DST; state.pc = NESTEST_DST;
//a little cheat to simulate probably a JSR and SEI at the beginning
state.sp = 0xfd;
state.flags.i = 1;
do{ do{
char* dasm = disassemble_6502_to_string(state.memory, state.pc); char* dasm = disassemble_6502_to_string(state.memory, state.pc);
printf("%-50s A:%02X X:%02X Y:%02X P:%02X SP:%02X\n", dasm, state.a, state.x, state.y, flags_as_byte(&state), state.sp); printf("%-50s A:%02X X:%02X Y:%02X P:%02X SP:%02X\n", dasm, state.a, state.x, state.y, debug_flags_as_byte(&state), state.sp);
emulate_6502_op(&state); emulate_6502_op(&state);
} while (state.flags.b != 1); } while (state.flags.b != 1);
} }
int main() int main()
{ {
//run_nestest(); run_nestest();
run_tests(); //run_tests();
return 0; return 0;
} }

16
flags.h
View File

@ -4,12 +4,12 @@
typedef struct Flags { typedef struct Flags {
//flags high to low: NV-BDIZC //flags high to low: NV-BDIZC
uint8_t c : 1; //set if last operation caused an overflow from bit 7 of the result or an underflow from bit 0 uint8_t c : 1; //0 - set if last operation caused an overflow from bit 7 of the result or an underflow from bit 0
uint8_t z : 1; //set if the result of the last operation was zero uint8_t z : 1; //1 - set if the result of the last operation was zero
uint8_t i : 1; //set with SEI and cleared with CLI uint8_t i : 1; //2 - set with SEI and cleared with CLI
uint8_t d : 1; //set with SEC and cleared with CLD uint8_t d : 1; //3 - set with SEC and cleared with CLD
uint8_t b : 1; //set when BRK executed uint8_t b : 1; //4 - set when BRK executed
uint8_t pad : 1; //not used uint8_t pad : 1; //5 - not used
uint8_t v : 1; //if the result has yielded an invalid two's complement result uint8_t v : 1; //6 - if the result has yielded an invalid two's complement result
uint8_t n : 1; //set if the result of the last operation set bit 7 to one uint8_t n : 1; //7 - set if the result of the last operation set bit 7 to one
} Flags; } Flags;

View File

@ -2001,7 +2001,6 @@ void test_PHP() {
state.flags.d = 1; state.flags.d = 1;
state.flags.i = 1; state.flags.i = 1;
state.flags.v = 1; state.flags.v = 1;
state.sp = 0xFF;
//arrange //arrange
char program[] = { PHP }; char program[] = { PHP };
@ -2018,6 +2017,27 @@ void test_PHP() {
test_cleanup(&state); test_cleanup(&state);
} }
void test_PLP_no_flags() {
//initialize
State6502 state = create_blank_state();
//no flags are set
//arrange
char program[] = { PHP };
memcpy(state.memory, program, sizeof(program));
//act
test_step(&state);
//assert
assert_sp(&state, 0xFE);
byte expected_value = (1 << 4) | (1 << 5);
assert_memory(&state, 0x1FF, expected_value);
//cleanup
test_cleanup(&state);
}
void test_PLP() { void test_PLP() {
State6502 state = create_blank_state(); State6502 state = create_blank_state();
state.sp = 0xFE; state.sp = 0xFE;
@ -2051,7 +2071,7 @@ void test_PLP2() {
//arrange //arrange
char program[] = { PLP }; char program[] = { PLP };
memcpy(state.memory, program, sizeof(program)); memcpy(state.memory, program, sizeof(program));
state.memory[0x1FF] = 0x04; //all flags should be on state.memory[0x1FF] = 0x04; //only flag i should be set
//act //act
test_step(&state); test_step(&state);
@ -2494,7 +2514,7 @@ fp* tests_eor[] = { test_EOR_IMM, test_EOR_ZP, test_EOR_ZPX, test_EOR_ABS, test_
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_PLA_N, test_PLA_Z, test_PHA_PLA }; fp* tests_pha_pla[] = { test_PHA, test_PLA, test_PLA_N, test_PLA_Z, test_PHA_PLA };
fp* tests_txs_tsx[] = { test_TXS, test_TSX, test_TXS_Z }; fp* tests_txs_tsx[] = { test_TXS, test_TSX, test_TXS_Z };
fp* tests_php_plp[] = { test_PHP, test_PLP, test_PLP2 }; fp* tests_php_plp[] = { test_PHP, test_PLP_no_flags, test_PLP, test_PLP2 };
fp* tests_jmp[] = { test_JMP, test_JMP_IND, test_JMP_IND_wrap }; fp* tests_jmp[] = { test_JMP, test_JMP_IND, test_JMP_IND_wrap };
fp* tests_cmp[] = { test_CMP_ABS_equal, test_CMP_ABS_greater, test_CMP_ABS_greater_2, test_CMP_ABS_less_than, test_CPX_ABS, test_CPY_ABS }; fp* tests_cmp[] = { test_CMP_ABS_equal, test_CMP_ABS_greater, test_CMP_ABS_greater_2, test_CMP_ABS_less_than, test_CPX_ABS, test_CPY_ABS };
fp* tests_sbc[] = { test_SBC_IMM_multiple }; fp* tests_sbc[] = { test_SBC_IMM_multiple };