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_
|
#ifndef _MOS6502_DIS_H_
|
||||||
#define _MOS6502_DIS_H_
|
#define _MOS6502_DIS_H_
|
||||||
|
|
||||||
|
#include "mos6502.h"
|
||||||
#include "vm_bits.h"
|
#include "vm_bits.h"
|
||||||
#include "vm_segment.h"
|
|
||||||
|
|
||||||
extern bool mos6502_dis_is_jump_label(int);
|
extern bool mos6502_dis_is_jump_label(int);
|
||||||
extern int mos6502_dis_expected_bytes(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_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_jump_unlabel(int);
|
||||||
extern void mos6502_dis_label(FILE *, int);
|
extern void mos6502_dis_label(FILE *, int);
|
||||||
extern void mos6502_dis_operand(FILE *, vm_segment *, int, int, vm_16bit);
|
extern void mos6502_dis_operand(mos6502 *, FILE *, int, int, vm_16bit);
|
||||||
extern void mos6502_dis_scan(FILE *, vm_segment *, int, int);
|
extern void mos6502_dis_scan(mos6502 *, FILE *, int, int);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -79,8 +79,8 @@ static char *instruction_strings[] = {
|
|||||||
* type.
|
* type.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
mos6502_dis_operand(FILE *stream,
|
mos6502_dis_operand(mos6502 *cpu,
|
||||||
vm_segment *segment,
|
FILE *stream,
|
||||||
int address,
|
int address,
|
||||||
int addr_mode,
|
int addr_mode,
|
||||||
vm_16bit value)
|
vm_16bit value)
|
||||||
@ -106,8 +106,8 @@ mos6502_dis_operand(FILE *stream,
|
|||||||
case IMP:
|
case IMP:
|
||||||
break;
|
break;
|
||||||
case IND:
|
case IND:
|
||||||
ind_address = vm_segment_get(segment, value) << 8;
|
ind_address = vm_segment_get(cpu->memory, value) << 8;
|
||||||
ind_address |= vm_segment_get(segment, value + 1);
|
ind_address |= vm_segment_get(cpu->memory, value + 1);
|
||||||
if (jump_table[ind_address]) {
|
if (jump_table[ind_address]) {
|
||||||
mos6502_dis_label(stream, ind_address);
|
mos6502_dis_label(stream, ind_address);
|
||||||
} else {
|
} 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
|
* 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
|
* operand to the file stream if one is warranted. We return the number
|
||||||
* of bytes consumed by scanning past the opcode and/or operand.
|
* of bytes consumed by scanning past the opcode and/or operand.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
mos6502_dis_opcode(FILE *stream, vm_segment *segment, int address)
|
mos6502_dis_opcode(mos6502 *cpu, FILE *stream, int address)
|
||||||
{
|
{
|
||||||
vm_8bit opcode;
|
vm_8bit opcode;
|
||||||
vm_16bit operand;
|
vm_16bit operand;
|
||||||
@ -216,7 +216,7 @@ mos6502_dis_opcode(FILE *stream, vm_segment *segment, int address)
|
|||||||
int expected;
|
int expected;
|
||||||
|
|
||||||
// The next byte is assumed to be the opcode we work with.
|
// 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
|
// And given that opcode, we need to see how many bytes large our
|
||||||
// operand will be.
|
// 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
|
// 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
|
// MSB and our operand will need to shift it 8 positions to
|
||||||
// the left before it can be OR'd.
|
// the left before it can be OR'd.
|
||||||
operand |= vm_segment_get(segment, address) << 8;
|
operand |= vm_segment_get(cpu->memory, address) << 8;
|
||||||
address++;
|
address++;
|
||||||
|
|
||||||
// Note we fall through here to the next case...
|
// 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
|
// the LSB space which simply requires we OR the byte
|
||||||
// directly in. If this is part of a two-byte operand, then
|
// directly in. If this is part of a two-byte operand, then
|
||||||
// the same logic still applies.
|
// the same logic still applies.
|
||||||
operand |= vm_segment_get(segment, address);
|
operand |= vm_segment_get(cpu->memory, address);
|
||||||
address++;
|
address++;
|
||||||
|
|
||||||
// And, in any other case (e.g. 0), we are done; we don't
|
// 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
|
// to a different spot in the program, then let's label this in the
|
||||||
// jump table.
|
// jump table.
|
||||||
if (stream == NULL && mos6502_would_jump(inst_code)) {
|
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
|
// 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, " ");
|
fprintf(stream, " ");
|
||||||
|
|
||||||
// Print out the operand given the proper address mode.
|
// 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.
|
// And let's terminate the line.
|
||||||
@ -310,16 +310,16 @@ mos6502_dis_opcode(FILE *stream, vm_segment *segment, int address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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) {
|
while (pos < end) {
|
||||||
pos += mos6502_dis_opcode(stream, segment, pos);
|
pos += mos6502_dis_opcode(cpu, stream, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mos6502_dis_jump_label(vm_16bit operand,
|
mos6502_dis_jump_label(mos6502 *cpu,
|
||||||
vm_segment *segment,
|
vm_16bit operand,
|
||||||
int address,
|
int address,
|
||||||
int addr_mode)
|
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
|
// of the operand as a kind of double pointer, or just re-watch
|
||||||
// Inception.
|
// Inception.
|
||||||
case IND:
|
case IND:
|
||||||
jump_loc = vm_segment_get(segment, operand) << 8;
|
jump_loc = vm_segment_get(cpu->memory, operand) << 8;
|
||||||
jump_loc |= vm_segment_get(segment, operand + 1);
|
jump_loc |= vm_segment_get(cpu->memory, operand + 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// In relative address mode, the jump location will be a
|
// In relative address mode, the jump location will be a
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <criterion/criterion.h>
|
#include <criterion/criterion.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "mos6502.h"
|
||||||
#include "mos6502.dis.h"
|
#include "mos6502.dis.h"
|
||||||
#include "mos6502.enums.h"
|
#include "mos6502.enums.h"
|
||||||
|
|
||||||
@ -15,7 +16,7 @@ static char buf[BUFSIZ];
|
|||||||
* code into.
|
* code into.
|
||||||
*/
|
*/
|
||||||
static FILE *stream = NULL;
|
static FILE *stream = NULL;
|
||||||
static vm_segment *segment = NULL;
|
static mos6502 *cpu = NULL;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -38,14 +39,14 @@ setup()
|
|||||||
// don't do that :D
|
// don't do that :D
|
||||||
setvbuf(stream, buf, _IOFBF, 256);
|
setvbuf(stream, buf, _IOFBF, 256);
|
||||||
|
|
||||||
segment = vm_segment_create(65536);
|
cpu = mos6502_create();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
teardown()
|
teardown()
|
||||||
{
|
{
|
||||||
fclose(stream);
|
fclose(stream);
|
||||||
vm_segment_free(segment);
|
mos6502_free(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -71,53 +72,53 @@ TestSuite(mos6502_dis, .init = setup, .fini = teardown);
|
|||||||
|
|
||||||
Test(mos6502_dis, operand)
|
Test(mos6502_dis, operand)
|
||||||
{
|
{
|
||||||
mos6502_dis_operand(stream, segment, 0, ABS, 0x1234);
|
mos6502_dis_operand(cpu, stream, 0, ABS, 0x1234);
|
||||||
assert_buf("$1234");
|
assert_buf("$1234");
|
||||||
mos6502_dis_operand(stream, segment, 0, ABX, 0x1234);
|
mos6502_dis_operand(cpu, stream, 0, ABX, 0x1234);
|
||||||
assert_buf("$1234,X");
|
assert_buf("$1234,X");
|
||||||
mos6502_dis_operand(stream, segment, 0, ABY, 0x1234);
|
mos6502_dis_operand(cpu, stream, 0, ABY, 0x1234);
|
||||||
assert_buf("$1234,Y");
|
assert_buf("$1234,Y");
|
||||||
mos6502_dis_operand(stream, segment, 0, IMM, 0x12);
|
mos6502_dis_operand(cpu, stream, 0, IMM, 0x12);
|
||||||
assert_buf("#$12");
|
assert_buf("#$12");
|
||||||
|
|
||||||
vm_segment_set(segment, 0x1234, 0x33);
|
vm_segment_set(cpu->memory, 0x1234, 0x33);
|
||||||
vm_segment_set(segment, 0x1235, 0x48);
|
vm_segment_set(cpu->memory, 0x1235, 0x48);
|
||||||
|
|
||||||
// For JMPs and JSRs (and BRKs), this should be a label and not a
|
// 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
|
// literal value. So we need to test both the literal and
|
||||||
// jump-labeled version.
|
// jump-labeled version.
|
||||||
mos6502_dis_operand(stream, segment, 0, IND, 0x1234);
|
mos6502_dis_operand(cpu, stream, 0, IND, 0x1234);
|
||||||
assert_buf("($1234)");
|
assert_buf("($1234)");
|
||||||
mos6502_dis_jump_label(0x1234, segment, 0, IND);
|
mos6502_dis_jump_label(cpu, 0x1234, 0, IND);
|
||||||
mos6502_dis_operand(stream, segment, 0, IND, 0x1234);
|
mos6502_dis_operand(cpu, stream, 0, IND, 0x1234);
|
||||||
assert_buf("ADDR_13128"); // = 0x1234
|
assert_buf("ADDR_13128"); // = 0x1234
|
||||||
|
|
||||||
// Let's undo our label above...
|
// Let's undo our label above...
|
||||||
mos6502_dis_jump_unlabel(0x1234);
|
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)");
|
assert_buf("($12,X)");
|
||||||
mos6502_dis_operand(stream, segment, 0, IDY, 0x34);
|
mos6502_dis_operand(cpu, stream, 0, IDY, 0x34);
|
||||||
assert_buf("($34),Y");
|
assert_buf("($34),Y");
|
||||||
mos6502_dis_operand(stream, segment, 0, ZPG, 0x34);
|
mos6502_dis_operand(cpu, stream, 0, ZPG, 0x34);
|
||||||
assert_buf("$34");
|
assert_buf("$34");
|
||||||
mos6502_dis_operand(stream, segment, 0, ZPX, 0x34);
|
mos6502_dis_operand(cpu, stream, 0, ZPX, 0x34);
|
||||||
assert_buf("$34,X");
|
assert_buf("$34,X");
|
||||||
mos6502_dis_operand(stream, segment, 0, ZPY, 0x34);
|
mos6502_dis_operand(cpu, stream, 0, ZPY, 0x34);
|
||||||
assert_buf("$34,Y");
|
assert_buf("$34,Y");
|
||||||
|
|
||||||
// These should both end up printing nothing
|
// 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("");
|
assert_buf("");
|
||||||
mos6502_dis_operand(stream, segment, 0, IMP, 0);
|
mos6502_dis_operand(cpu, stream, 0, IMP, 0);
|
||||||
assert_buf("");
|
assert_buf("");
|
||||||
|
|
||||||
// Test a forward jump (operand < 128)
|
// 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");
|
assert_buf("ADDR_552");
|
||||||
|
|
||||||
// Test a backward jump (operand >= 128)
|
// 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");
|
assert_buf("ADDR_396");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,29 +208,26 @@ Test(mos6502_dis, expected_bytes)
|
|||||||
|
|
||||||
Test(mos6502_dis, opcode)
|
Test(mos6502_dis, opcode)
|
||||||
{
|
{
|
||||||
vm_segment *segment;
|
|
||||||
int bytes;
|
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)
|
bytes = mos6502_dis_opcode(cpu, stream, 0);
|
||||||
vm_segment_set(segment, 1, 0x38);
|
|
||||||
|
|
||||||
bytes = mos6502_dis_opcode(stream, segment, 0);
|
|
||||||
assert_buf(" AND #$38\n");
|
assert_buf(" AND #$38\n");
|
||||||
cr_assert_eq(bytes, 2);
|
cr_assert_eq(bytes, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
Test(mos6502_dis, scan)
|
Test(mos6502_dis, scan)
|
||||||
{
|
{
|
||||||
vm_segment_set(segment, 0, 0x29); // AND (imm)
|
vm_segment_set(cpu->memory, 0, 0x29); // AND (imm)
|
||||||
vm_segment_set(segment, 1, 0x38);
|
vm_segment_set(cpu->memory, 1, 0x38);
|
||||||
vm_segment_set(segment, 2, 0x88); // DEY (imp)
|
vm_segment_set(cpu->memory, 2, 0x88); // DEY (imp)
|
||||||
vm_segment_set(segment, 3, 0x6C); // JMP (ind)
|
vm_segment_set(cpu->memory, 3, 0x6C); // JMP (ind)
|
||||||
vm_segment_set(segment, 4, 0x12);
|
vm_segment_set(cpu->memory, 4, 0x12);
|
||||||
vm_segment_set(segment, 5, 0x34);
|
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"
|
assert_buf(" AND #$38\n"
|
||||||
" DEY\n"
|
" DEY\n"
|
||||||
@ -241,21 +239,21 @@ Test(mos6502_dis, jump_label)
|
|||||||
{
|
{
|
||||||
cr_assert_eq(mos6502_dis_is_jump_label(123), false);
|
cr_assert_eq(mos6502_dis_is_jump_label(123), false);
|
||||||
|
|
||||||
vm_segment_set(segment, 123, 0);
|
vm_segment_set(cpu->memory, 123, 0);
|
||||||
vm_segment_set(segment, 124, 5);
|
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);
|
cr_assert_eq(mos6502_dis_is_jump_label(5), true);
|
||||||
mos6502_dis_jump_unlabel(123);
|
mos6502_dis_jump_unlabel(123);
|
||||||
cr_assert_eq(mos6502_dis_is_jump_label(123), false);
|
cr_assert_eq(mos6502_dis_is_jump_label(123), false);
|
||||||
|
|
||||||
// Testing forward relative
|
// 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);
|
cr_assert_eq(mos6502_dis_is_jump_label(123 + 10), true);
|
||||||
mos6502_dis_jump_unlabel(123 + 10);
|
mos6502_dis_jump_unlabel(123 + 10);
|
||||||
|
|
||||||
// Testing backward relative
|
// 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);
|
cr_assert_eq(mos6502_dis_is_jump_label(133 + 1000 - 256), true);
|
||||||
mos6502_dis_jump_unlabel(133 + 1000 - 256);
|
mos6502_dis_jump_unlabel(133 + 1000 - 256);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user