1
0
mirror of https://github.com/pevans/erc-c.git synced 2024-12-21 08:30:55 +00:00

Refactor to use cpu, not literal segments

This commit is contained in:
Peter Evans 2017-12-30 23:02:30 -06:00
parent b42d5370aa
commit ead5f28e79
3 changed files with 59 additions and 61 deletions

View File

@ -1,17 +1,17 @@
#ifndef _MOS6502_DIS_H_
#define _MOS6502_DIS_H_
#include "mos6502.h"
#include "vm_bits.h"
#include "vm_segment.h"
extern bool mos6502_dis_is_jump_label(int);
extern int mos6502_dis_expected_bytes(int);
extern int mos6502_dis_opcode(FILE *, vm_segment *, int);
extern int mos6502_dis_opcode(mos6502 *, FILE *, int);
extern void mos6502_dis_instruction(FILE *, int);
extern void mos6502_dis_jump_label(vm_16bit, vm_segment *, int, int);
extern void mos6502_dis_jump_label(mos6502 *, vm_16bit, int, int);
extern void mos6502_dis_jump_unlabel(int);
extern void mos6502_dis_label(FILE *, int);
extern void mos6502_dis_operand(FILE *, vm_segment *, int, int, vm_16bit);
extern void mos6502_dis_scan(FILE *, vm_segment *, int, int);
extern void mos6502_dis_operand(mos6502 *, FILE *, int, int, vm_16bit);
extern void mos6502_dis_scan(mos6502 *, FILE *, int, int);
#endif

View File

@ -79,8 +79,8 @@ static char *instruction_strings[] = {
* type.
*/
void
mos6502_dis_operand(FILE *stream,
vm_segment *segment,
mos6502_dis_operand(mos6502 *cpu,
FILE *stream,
int address,
int addr_mode,
vm_16bit value)
@ -106,8 +106,8 @@ mos6502_dis_operand(FILE *stream,
case IMP:
break;
case IND:
ind_address = vm_segment_get(segment, value) << 8;
ind_address |= vm_segment_get(segment, value + 1);
ind_address = vm_segment_get(cpu->memory, value) << 8;
ind_address |= vm_segment_get(cpu->memory, value + 1);
if (jump_table[ind_address]) {
mos6502_dis_label(stream, ind_address);
} else {
@ -201,13 +201,13 @@ mos6502_dis_expected_bytes(int addr_mode)
}
/*
* Scan the segment (with a given address) and write the opcode at that
* Scan memory (with a given address) and write the opcode at that
* point to the given file stream. This function will also write an
* operand to the file stream if one is warranted. We return the number
* of bytes consumed by scanning past the opcode and/or operand.
*/
int
mos6502_dis_opcode(FILE *stream, vm_segment *segment, int address)
mos6502_dis_opcode(mos6502 *cpu, FILE *stream, int address)
{
vm_8bit opcode;
vm_16bit operand;
@ -216,7 +216,7 @@ mos6502_dis_opcode(FILE *stream, vm_segment *segment, int address)
int expected;
// The next byte is assumed to be the opcode we work with.
opcode = vm_segment_get(segment, address);
opcode = vm_segment_get(cpu->memory, address);
// And given that opcode, we need to see how many bytes large our
// operand will be.
@ -239,7 +239,7 @@ mos6502_dis_opcode(FILE *stream, vm_segment *segment, int address)
// If we have a two-byte operand, then the first byte is the
// MSB and our operand will need to shift it 8 positions to
// the left before it can be OR'd.
operand |= vm_segment_get(segment, address) << 8;
operand |= vm_segment_get(cpu->memory, address) << 8;
address++;
// Note we fall through here to the next case...
@ -249,7 +249,7 @@ mos6502_dis_opcode(FILE *stream, vm_segment *segment, int address)
// the LSB space which simply requires we OR the byte
// directly in. If this is part of a two-byte operand, then
// the same logic still applies.
operand |= vm_segment_get(segment, address);
operand |= vm_segment_get(cpu->memory, address);
address++;
// And, in any other case (e.g. 0), we are done; we don't
@ -263,7 +263,7 @@ mos6502_dis_opcode(FILE *stream, vm_segment *segment, int address)
// to a different spot in the program, then let's label this in the
// jump table.
if (stream == NULL && mos6502_would_jump(inst_code)) {
mos6502_dis_jump_label(operand, segment, address, addr_mode);
mos6502_dis_jump_label(cpu, operand, address, addr_mode);
}
// It's totally possible that we are not expected to print out the
@ -296,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, segment, address, addr_mode, operand);
mos6502_dis_operand(cpu, stream, address, addr_mode, operand);
}
// And let's terminate the line.
@ -310,16 +310,16 @@ mos6502_dis_opcode(FILE *stream, vm_segment *segment, int address)
}
void
mos6502_dis_scan(FILE *stream, vm_segment *segment, int pos, int end)
mos6502_dis_scan(mos6502 *cpu, FILE *stream, int pos, int end)
{
while (pos < end) {
pos += mos6502_dis_opcode(stream, segment, pos);
pos += mos6502_dis_opcode(cpu, stream, pos);
}
}
void
mos6502_dis_jump_label(vm_16bit operand,
vm_segment *segment,
mos6502_dis_jump_label(mos6502 *cpu,
vm_16bit operand,
int address,
int addr_mode)
{
@ -332,8 +332,8 @@ mos6502_dis_jump_label(vm_16bit operand,
// of the operand as a kind of double pointer, or just re-watch
// Inception.
case IND:
jump_loc = vm_segment_get(segment, operand) << 8;
jump_loc |= vm_segment_get(segment, operand + 1);
jump_loc = vm_segment_get(cpu->memory, operand) << 8;
jump_loc |= vm_segment_get(cpu->memory, operand + 1);
break;
// In relative address mode, the jump location will be a

View File

@ -1,6 +1,7 @@
#include <criterion/criterion.h>
#include <unistd.h>
#include "mos6502.h"
#include "mos6502.dis.h"
#include "mos6502.enums.h"
@ -15,7 +16,7 @@ static char buf[BUFSIZ];
* code into.
*/
static FILE *stream = NULL;
static vm_segment *segment = NULL;
static mos6502 *cpu = NULL;
static void
@ -38,14 +39,14 @@ setup()
// don't do that :D
setvbuf(stream, buf, _IOFBF, 256);
segment = vm_segment_create(65536);
cpu = mos6502_create();
}
static void
teardown()
{
fclose(stream);
vm_segment_free(segment);
mos6502_free(cpu);
}
static void
@ -71,53 +72,53 @@ TestSuite(mos6502_dis, .init = setup, .fini = teardown);
Test(mos6502_dis, operand)
{
mos6502_dis_operand(stream, segment, 0, ABS, 0x1234);
mos6502_dis_operand(cpu, stream, 0, ABS, 0x1234);
assert_buf("$1234");
mos6502_dis_operand(stream, segment, 0, ABX, 0x1234);
mos6502_dis_operand(cpu, stream, 0, ABX, 0x1234);
assert_buf("$1234,X");
mos6502_dis_operand(stream, segment, 0, ABY, 0x1234);
mos6502_dis_operand(cpu, stream, 0, ABY, 0x1234);
assert_buf("$1234,Y");
mos6502_dis_operand(stream, segment, 0, IMM, 0x12);
mos6502_dis_operand(cpu, stream, 0, IMM, 0x12);
assert_buf("#$12");
vm_segment_set(segment, 0x1234, 0x33);
vm_segment_set(segment, 0x1235, 0x48);
vm_segment_set(cpu->memory, 0x1234, 0x33);
vm_segment_set(cpu->memory, 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, segment, 0, IND, 0x1234);
mos6502_dis_operand(cpu, stream, 0, IND, 0x1234);
assert_buf("($1234)");
mos6502_dis_jump_label(0x1234, segment, 0, IND);
mos6502_dis_operand(stream, segment, 0, IND, 0x1234);
mos6502_dis_jump_label(cpu, 0x1234, 0, IND);
mos6502_dis_operand(cpu, stream, 0, IND, 0x1234);
assert_buf("ADDR_13128"); // = 0x1234
// Let's undo our label above...
mos6502_dis_jump_unlabel(0x1234);
mos6502_dis_operand(stream, segment, 0, IDX, 0x12);
mos6502_dis_operand(cpu, stream, 0, IDX, 0x12);
assert_buf("($12,X)");
mos6502_dis_operand(stream, segment, 0, IDY, 0x34);
mos6502_dis_operand(cpu, stream, 0, IDY, 0x34);
assert_buf("($34),Y");
mos6502_dis_operand(stream, segment, 0, ZPG, 0x34);
mos6502_dis_operand(cpu, stream, 0, ZPG, 0x34);
assert_buf("$34");
mos6502_dis_operand(stream, segment, 0, ZPX, 0x34);
mos6502_dis_operand(cpu, stream, 0, ZPX, 0x34);
assert_buf("$34,X");
mos6502_dis_operand(stream, segment, 0, ZPY, 0x34);
mos6502_dis_operand(cpu, stream, 0, ZPY, 0x34);
assert_buf("$34,Y");
// These should both end up printing nothing
mos6502_dis_operand(stream, segment, 0, ACC, 0);
mos6502_dis_operand(cpu, stream, 0, ACC, 0);
assert_buf("");
mos6502_dis_operand(stream, segment, 0, IMP, 0);
mos6502_dis_operand(cpu, stream, 0, IMP, 0);
assert_buf("");
// Test a forward jump (operand < 128)
mos6502_dis_operand(stream, segment, 500, REL, 52);
mos6502_dis_operand(cpu, stream, 500, REL, 52);
assert_buf("ADDR_552");
// Test a backward jump (operand >= 128)
mos6502_dis_operand(stream, segment, 500, REL, 152);
mos6502_dis_operand(cpu, stream, 500, REL, 152);
assert_buf("ADDR_396");
}
@ -207,29 +208,26 @@ Test(mos6502_dis, expected_bytes)
Test(mos6502_dis, opcode)
{
vm_segment *segment;
int bytes;
segment = vm_segment_create(1000);
vm_segment_set(cpu->memory, 0, 0x29); // AND (imm)
vm_segment_set(cpu->memory, 1, 0x38);
vm_segment_set(segment, 0, 0x29); // AND (imm)
vm_segment_set(segment, 1, 0x38);
bytes = mos6502_dis_opcode(stream, segment, 0);
bytes = mos6502_dis_opcode(cpu, stream, 0);
assert_buf(" AND #$38\n");
cr_assert_eq(bytes, 2);
}
Test(mos6502_dis, scan)
{
vm_segment_set(segment, 0, 0x29); // AND (imm)
vm_segment_set(segment, 1, 0x38);
vm_segment_set(segment, 2, 0x88); // DEY (imp)
vm_segment_set(segment, 3, 0x6C); // JMP (ind)
vm_segment_set(segment, 4, 0x12);
vm_segment_set(segment, 5, 0x34);
vm_segment_set(cpu->memory, 0, 0x29); // AND (imm)
vm_segment_set(cpu->memory, 1, 0x38);
vm_segment_set(cpu->memory, 2, 0x88); // DEY (imp)
vm_segment_set(cpu->memory, 3, 0x6C); // JMP (ind)
vm_segment_set(cpu->memory, 4, 0x12);
vm_segment_set(cpu->memory, 5, 0x34);
mos6502_dis_scan(stream, segment, 0, 6);
mos6502_dis_scan(cpu, stream, 0, 6);
assert_buf(" AND #$38\n"
" DEY\n"
@ -241,21 +239,21 @@ 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);
vm_segment_set(cpu->memory, 123, 0);
vm_segment_set(cpu->memory, 124, 5);
mos6502_dis_jump_label(123, segment, 0, IND);
mos6502_dis_jump_label(cpu, 123, 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, segment, 10, REL);
mos6502_dis_jump_label(cpu, 123, 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, segment, 1000, REL);
mos6502_dis_jump_label(cpu, 133, 1000, REL);
cr_assert_eq(mos6502_dis_is_jump_label(133 + 1000 - 256), true);
mos6502_dis_jump_unlabel(133 + 1000 - 256);
}