From b42d5370aa449d25ac7053988339ce71a331e7a3 Mon Sep 17 00:00:00 2001 From: Peter Evans Date: Sat, 30 Dec 2017 22:50:23 -0600 Subject: [PATCH] Small bug in the jump label code for IND This also required a rethink on some core functions which now needed to know about the memory segment; and further changes in the unit-testing code on the disassembly suite was also necessary. --- include/mos6502.dis.h | 2 +- src/mos6502.dis.c | 15 +++++++++--- tests/mos6502.dis.c | 57 ++++++++++++++++++++++++------------------- 3 files changed, 44 insertions(+), 30 deletions(-) diff --git a/include/mos6502.dis.h b/include/mos6502.dis.h index d51d4b9..5ee37c2 100644 --- a/include/mos6502.dis.h +++ b/include/mos6502.dis.h @@ -11,7 +11,7 @@ extern void mos6502_dis_instruction(FILE *, int); extern void mos6502_dis_jump_label(vm_16bit, vm_segment *, int, int); extern void mos6502_dis_jump_unlabel(int); extern void mos6502_dis_label(FILE *, int); -extern void mos6502_dis_operand(FILE *, int, int, vm_16bit); +extern void mos6502_dis_operand(FILE *, vm_segment *, int, int, vm_16bit); extern void mos6502_dis_scan(FILE *, vm_segment *, int, int); #endif diff --git a/src/mos6502.dis.c b/src/mos6502.dis.c index 4aeba95..b206039 100644 --- a/src/mos6502.dis.c +++ b/src/mos6502.dis.c @@ -79,9 +79,14 @@ static char *instruction_strings[] = { * type. */ void -mos6502_dis_operand(FILE *stream, int address, int addr_mode, vm_16bit value) +mos6502_dis_operand(FILE *stream, + vm_segment *segment, + int address, + int addr_mode, + vm_16bit value) { int rel_address; + int ind_address; switch (addr_mode) { case ACC: @@ -101,8 +106,10 @@ mos6502_dis_operand(FILE *stream, int address, int addr_mode, vm_16bit value) case IMP: break; case IND: - if (jump_table[value]) { - mos6502_dis_label(stream, value); + ind_address = vm_segment_get(segment, value) << 8; + ind_address |= vm_segment_get(segment, value + 1); + if (jump_table[ind_address]) { + mos6502_dis_label(stream, ind_address); } else { fprintf(stream, "($%04X)", value); } @@ -289,7 +296,7 @@ mos6502_dis_opcode(FILE *stream, vm_segment *segment, int address) fprintf(stream, " "); // Print out the operand given the proper address mode. - mos6502_dis_operand(stream, address, addr_mode, operand); + mos6502_dis_operand(stream, segment, address, addr_mode, operand); } // And let's terminate the line. diff --git a/tests/mos6502.dis.c b/tests/mos6502.dis.c index 332d609..9dda9de 100644 --- a/tests/mos6502.dis.c +++ b/tests/mos6502.dis.c @@ -15,6 +15,8 @@ static char buf[BUFSIZ]; * code into. */ static FILE *stream = NULL; +static vm_segment *segment = NULL; + static void setup() @@ -35,12 +37,15 @@ setup() // check with Criterion. Uh, unless we blow out the buffer size... // don't do that :D setvbuf(stream, buf, _IOFBF, 256); + + segment = vm_segment_create(65536); } static void teardown() { fclose(stream); + vm_segment_free(segment); } static void @@ -66,50 +71,53 @@ TestSuite(mos6502_dis, .init = setup, .fini = teardown); Test(mos6502_dis, operand) { - mos6502_dis_operand(stream, 0, ABS, 0x1234); + mos6502_dis_operand(stream, segment, 0, ABS, 0x1234); assert_buf("$1234"); - mos6502_dis_operand(stream, 0, ABX, 0x1234); + mos6502_dis_operand(stream, segment, 0, ABX, 0x1234); assert_buf("$1234,X"); - mos6502_dis_operand(stream, 0, ABY, 0x1234); + mos6502_dis_operand(stream, segment, 0, ABY, 0x1234); assert_buf("$1234,Y"); - mos6502_dis_operand(stream, 0, IMM, 0x12); + mos6502_dis_operand(stream, segment, 0, IMM, 0x12); assert_buf("#$12"); + vm_segment_set(segment, 0x1234, 0x33); + vm_segment_set(segment, 0x1235, 0x48); + // For JMPs and JSRs (and BRKs), this should be a label and not a // literal value. So we need to test both the literal and // jump-labeled version. - mos6502_dis_operand(stream, 0, IND, 0x1234); + mos6502_dis_operand(stream, segment, 0, IND, 0x1234); assert_buf("($1234)"); - mos6502_dis_jump_label(0x1234, 0, IND); - mos6502_dis_operand(stream, 0, IND, 0x1234); - assert_buf("ADDR_4660"); // = 0x1234 + mos6502_dis_jump_label(0x1234, segment, 0, IND); + mos6502_dis_operand(stream, segment, 0, IND, 0x1234); + assert_buf("ADDR_13128"); // = 0x1234 // Let's undo our label above... mos6502_dis_jump_unlabel(0x1234); - mos6502_dis_operand(stream, 0, IDX, 0x12); + mos6502_dis_operand(stream, segment, 0, IDX, 0x12); assert_buf("($12,X)"); - mos6502_dis_operand(stream, 0, IDY, 0x34); + mos6502_dis_operand(stream, segment, 0, IDY, 0x34); assert_buf("($34),Y"); - mos6502_dis_operand(stream, 0, ZPG, 0x34); + mos6502_dis_operand(stream, segment, 0, ZPG, 0x34); assert_buf("$34"); - mos6502_dis_operand(stream, 0, ZPX, 0x34); + mos6502_dis_operand(stream, segment, 0, ZPX, 0x34); assert_buf("$34,X"); - mos6502_dis_operand(stream, 0, ZPY, 0x34); + mos6502_dis_operand(stream, segment, 0, ZPY, 0x34); assert_buf("$34,Y"); // These should both end up printing nothing - mos6502_dis_operand(stream, 0, ACC, 0); + mos6502_dis_operand(stream, segment, 0, ACC, 0); assert_buf(""); - mos6502_dis_operand(stream, 0, IMP, 0); + mos6502_dis_operand(stream, segment, 0, IMP, 0); assert_buf(""); // Test a forward jump (operand < 128) - mos6502_dis_operand(stream, 500, REL, 52); + mos6502_dis_operand(stream, segment, 500, REL, 52); assert_buf("ADDR_552"); // Test a backward jump (operand >= 128) - mos6502_dis_operand(stream, 500, REL, 152); + mos6502_dis_operand(stream, segment, 500, REL, 152); assert_buf("ADDR_396"); } @@ -214,10 +222,6 @@ Test(mos6502_dis, opcode) Test(mos6502_dis, scan) { - vm_segment *segment; - - segment = vm_segment_create(1000); - vm_segment_set(segment, 0, 0x29); // AND (imm) vm_segment_set(segment, 1, 0x38); vm_segment_set(segment, 2, 0x88); // DEY (imp) @@ -236,19 +240,22 @@ Test(mos6502_dis, scan) Test(mos6502_dis, jump_label) { cr_assert_eq(mos6502_dis_is_jump_label(123), false); + + vm_segment_set(segment, 123, 0); + vm_segment_set(segment, 124, 5); - mos6502_dis_jump_label(123, 0, IND); - cr_assert_eq(mos6502_dis_is_jump_label(123), true); + mos6502_dis_jump_label(123, segment, 0, IND); + cr_assert_eq(mos6502_dis_is_jump_label(5), true); mos6502_dis_jump_unlabel(123); cr_assert_eq(mos6502_dis_is_jump_label(123), false); // Testing forward relative - mos6502_dis_jump_label(123, 10, REL); + mos6502_dis_jump_label(123, segment, 10, REL); cr_assert_eq(mos6502_dis_is_jump_label(123 + 10), true); mos6502_dis_jump_unlabel(123 + 10); // Testing backward relative - mos6502_dis_jump_label(133, 1000, REL); + mos6502_dis_jump_label(133, segment, 1000, REL); cr_assert_eq(mos6502_dis_is_jump_label(133 + 1000 - 256), true); mos6502_dis_jump_unlabel(133 + 1000 - 256); }