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:
parent
b42d5370aa
commit
ead5f28e79
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user