mirror of
https://github.com/andrew-jacobs/emu816.git
synced 2025-03-27 20:30:16 +00:00
Made class methods static for greater performance
This commit is contained in:
parent
c3d347d906
commit
6638462e10
@ -3,10 +3,15 @@
|
||||
The repository contains the source code for a simple 65C816 emulator for Windows,
|
||||
Linux and the embedded ChipKIT platform.
|
||||
|
||||
This is the first release of the code and it has only had a limited amount of
|
||||
This is the second release of the code and it has only had a limited amount of
|
||||
testing. Currently there is no support for decimal arithmetic but the full
|
||||
instruction set is supported.
|
||||
|
||||
The major change since the last release has been the recoding of all the classes
|
||||
to make them static. This was done to increase the execution performance of the
|
||||
code. On my development laptop (AMD8 1.8GHz) it now runs at an emulated speed of
|
||||
around 225 MHz with full optimization.
|
||||
|
||||
There is no I/O at the moment or source of interrupts. Executing a WDM #$FF will
|
||||
cause the emulator to exit.
|
||||
|
||||
|
66
emu816.cc
66
emu816.cc
@ -9,7 +9,7 @@
|
||||
//
|
||||
// A Portable C++ WDC 65C816 Emulator
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (C)2016 Andrew John Jacobs
|
||||
// Copyright (C),2016 Andrew John Jacobs
|
||||
// All rights reserved.
|
||||
//
|
||||
// This work is made available under the terms of the Creative Commons
|
||||
@ -32,14 +32,32 @@
|
||||
using namespace std;
|
||||
#endif
|
||||
|
||||
union emu816::FLAGS emu816::p;
|
||||
|
||||
emu816::Bit emu816::e;
|
||||
|
||||
union emu816::REGS emu816::a;
|
||||
union emu816::REGS emu816::x;
|
||||
union emu816::REGS emu816::y;
|
||||
union emu816::REGS emu816::sp;
|
||||
union emu816::REGS emu816::dp;
|
||||
|
||||
emu816::Word emu816::pc;
|
||||
emu816::Byte emu816::pbr;
|
||||
emu816::Byte emu816::dbr;
|
||||
|
||||
bool emu816::stopped;
|
||||
bool emu816::interrupted;
|
||||
unsigned long emu816::cycles;
|
||||
bool emu816::trace;
|
||||
|
||||
//==============================================================================
|
||||
|
||||
// Construct a emu816 instance.
|
||||
emu816::emu816(mem816 &mem)
|
||||
: mem(mem)
|
||||
// Not used.
|
||||
emu816::emu816()
|
||||
{ }
|
||||
|
||||
// Destroy a emu816 instance.
|
||||
// Not used
|
||||
emu816::~emu816()
|
||||
{ }
|
||||
|
||||
@ -51,13 +69,13 @@ void emu816::reset(bool trace)
|
||||
dbr = 0x00 << 16;
|
||||
dp.w = 0x0000;
|
||||
sp.w = 0x0100;
|
||||
pc = mem.getWord(0xfffc);
|
||||
pc = getWord(0xfffc);
|
||||
p.b = 0x34;
|
||||
|
||||
stopped = false;
|
||||
interrupted = false;
|
||||
|
||||
this -> trace = trace;
|
||||
emu816::trace = trace;
|
||||
}
|
||||
|
||||
// Execute a single instruction or invoke an interrupt
|
||||
@ -67,7 +85,7 @@ void emu816::step()
|
||||
|
||||
SHOWPC();
|
||||
|
||||
switch (mem.getByte (join(pbr, pc++))) {
|
||||
switch (getByte (join(pbr, pc++))) {
|
||||
case 0x00: op_brk(am_immb()); break;
|
||||
case 0x01: op_ora(am_dpix()); break;
|
||||
case 0x02: op_cop(am_immb()); break;
|
||||
@ -357,7 +375,7 @@ void emu816::show()
|
||||
Serial.print (':');
|
||||
Serial.print (toHex(pc, 4));
|
||||
Serial.print (' ');
|
||||
Serial.print (toHex(mem.getByte(join(pbr, pc)), 2));
|
||||
Serial.print (toHex(getByte(join(pbr, pc)), 2));
|
||||
}
|
||||
|
||||
// Display the operand bytes
|
||||
@ -365,21 +383,21 @@ void emu816::bytes(unsigned int count)
|
||||
{
|
||||
if (count > 0) {
|
||||
Serial.print(' ');
|
||||
Serial.print(toHex(mem.getByte(bank(pbr) | (pc + 0)), 2));
|
||||
Serial.print(toHex(getByte(bank(pbr) | (pc + 0)), 2));
|
||||
}
|
||||
else
|
||||
Serial.print(" ");
|
||||
|
||||
if (count > 1) {
|
||||
Serial.print(' ');
|
||||
Serial.print(toHex(mem.getByte(bank(pbr) | (pc + 1)), 2));
|
||||
Serial.print(toHex(getByte(bank(pbr) | (pc + 1)), 2));
|
||||
}
|
||||
else
|
||||
Serial.print(" ");
|
||||
|
||||
if (count > 2) {
|
||||
Serial.print(' ');
|
||||
Serial.print(toHex(mem.getByte(bank(pbr) | (pc + 2)), 2));
|
||||
Serial.print(toHex(getByte(bank(pbr) | (pc + 2)), 2));
|
||||
}
|
||||
else
|
||||
Serial.print(" ");
|
||||
@ -461,13 +479,13 @@ void emu816::dump(const char *mnem, Addr ea)
|
||||
|
||||
Serial.print(" {");
|
||||
Serial.print(' ');
|
||||
Serial.print(toHex(mem.getByte(sp.w + 1), 2));
|
||||
Serial.print(toHex(getByte(sp.w + 1), 2));
|
||||
Serial.print(' ');
|
||||
Serial.print(toHex(mem.getByte(sp.w + 2), 2));
|
||||
Serial.print(toHex(getByte(sp.w + 2), 2));
|
||||
Serial.print(' ');
|
||||
Serial.print(toHex(mem.getByte(sp.w + 3), 2));
|
||||
Serial.print(toHex(getByte(sp.w + 3), 2));
|
||||
Serial.print(' ');
|
||||
Serial.print(toHex(mem.getByte(sp.w + 4), 2));
|
||||
Serial.print(toHex(getByte(sp.w + 4), 2));
|
||||
Serial.print(" }");
|
||||
|
||||
Serial.print(" DBR=");
|
||||
@ -480,24 +498,24 @@ void emu816::show()
|
||||
cout << '{' << toHex(cycles, 4) << "} ";
|
||||
cout << toHex(pbr, 2);
|
||||
cout << ':' << toHex(pc, 4);
|
||||
cout << ' ' << toHex(mem.getByte(join(pbr, pc)), 2);
|
||||
cout << ' ' << toHex(getByte(join(pbr, pc)), 2);
|
||||
}
|
||||
|
||||
// Display the operand bytes
|
||||
void emu816::bytes(unsigned int count)
|
||||
{
|
||||
if (count > 0)
|
||||
cout << ' ' << toHex(mem.getByte(bank(pbr) | (pc + 0)), 2);
|
||||
cout << ' ' << toHex(getByte(bank(pbr) | (pc + 0)), 2);
|
||||
else
|
||||
cout << " ";
|
||||
|
||||
if (count > 1)
|
||||
cout << ' ' << toHex(mem.getByte(bank(pbr) | (pc + 1)), 2);
|
||||
cout << ' ' << toHex(getByte(bank(pbr) | (pc + 1)), 2);
|
||||
else
|
||||
cout << " ";
|
||||
|
||||
if (count > 2)
|
||||
cout << ' ' << toHex(mem.getByte(bank(pbr) | (pc + 2)), 2);
|
||||
cout << ' ' << toHex(getByte(bank(pbr) | (pc + 2)), 2);
|
||||
else
|
||||
cout << " ";
|
||||
|
||||
@ -545,10 +563,10 @@ void emu816::dump(const char *mnem, Addr ea)
|
||||
cout << '[' << toHex(hi(sp.w), 2);
|
||||
cout << toHex(sp.b, 2) << ']';
|
||||
cout << " {";
|
||||
cout << ' ' << toHex(mem.getByte(sp.w + 1), 2);
|
||||
cout << ' ' << toHex(mem.getByte(sp.w + 2), 2);
|
||||
cout << ' ' << toHex(mem.getByte(sp.w + 3), 2);
|
||||
cout << ' ' << toHex(mem.getByte(sp.w + 4), 2);
|
||||
cout << ' ' << toHex(getByte(sp.w + 1), 2);
|
||||
cout << ' ' << toHex(getByte(sp.w + 2), 2);
|
||||
cout << ' ' << toHex(getByte(sp.w + 3), 2);
|
||||
cout << ' ' << toHex(getByte(sp.w + 4), 2);
|
||||
cout << " }";
|
||||
cout << " DBR=" << toHex(dbr, 2) << endl;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<Optimization>Custom</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@ -116,6 +116,7 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LocalDebuggerCommandArguments>-t examples/simple/simple.s28</LocalDebuggerCommandArguments>
|
||||
<LocalDebuggerCommandArguments>examples/simple/simple.s28</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LocalDebuggerCommandArguments>-t examples/simple/simple.s28</LocalDebuggerCommandArguments>
|
||||
<LocalDebuggerCommandArguments>examples/simple/simple.s28</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
</Project>
|
Binary file not shown.
@ -26,7 +26,7 @@ OBJS = \
|
||||
simple.obj
|
||||
|
||||
|
||||
all: simple.s28
|
||||
all: simple.s28 simple.hex
|
||||
|
||||
clean:
|
||||
$(RM) *.obj
|
||||
@ -39,6 +39,10 @@ clean:
|
||||
|
||||
simple.s28: $(OBJS)
|
||||
$(LK65) -bss $$0000-$$7FFF -code $$F000-$$FFFF -s28 -output $@ $(OBJS)
|
||||
|
||||
simple.hex: $(OBJS)
|
||||
$(LK65) -bss $$0000-$$7FFF -code $$F000-$$FFFF -hex -output $@ $(OBJS)
|
||||
java -cp $(DEV65_JAR) uk.co.demon.obelisk.util.Hex2C < simple.hex > simple.txt
|
||||
|
||||
#===============================================================================
|
||||
# Dependencies
|
||||
|
@ -47,15 +47,16 @@ RESET:
|
||||
lda #STACK
|
||||
tcs
|
||||
|
||||
ldy #2
|
||||
ldy #100
|
||||
repeat
|
||||
ldx #123
|
||||
ldx #0
|
||||
repeat
|
||||
dex
|
||||
until eq
|
||||
dey
|
||||
until eq
|
||||
wdm #$ff
|
||||
wdm #$ff
|
||||
bra RESET
|
||||
|
||||
;===============================================================================
|
||||
; Dummy Interrupt Handlers
|
||||
|
@ -168,18 +168,19 @@ Portable 65xx Assembler [16.06]
|
||||
00:F006 A9???? : lda #STACK
|
||||
00:F009 1B : tcs
|
||||
|
||||
00:F00A A00200 : ldy #2
|
||||
00:F00A A06400 : ldy #100
|
||||
|
||||
Portable 65xx Assembler [16.06]
|
||||
|
||||
repeat
|
||||
00:F00D A27B00 : ldx #123
|
||||
00:F00D A20000 : ldx #0
|
||||
repeat
|
||||
00:F010 CA : dex
|
||||
00:F011 D0FD : until eq
|
||||
00:F013 88 : dey
|
||||
00:F014 D0F7 : until eq
|
||||
00:F016 42FF : wdm #$ff
|
||||
00:F016 42FF : wdm #$ff
|
||||
00:F018 80E6 : bra RESET
|
||||
|
||||
;===============================================================================
|
||||
; Dummy Interrupt Handlers
|
||||
@ -190,13 +191,13 @@ Portable 65xx Assembler [16.06]
|
||||
ABORTN:
|
||||
NMIN:
|
||||
BRKN
|
||||
00:F018 80FE : bra $
|
||||
00:F01A 80FE : bra $
|
||||
|
||||
COP:
|
||||
ABORT:
|
||||
NMI:
|
||||
IRQBRK:
|
||||
00:F01A 80FE : bra $
|
||||
00:F01C 80FE : bra $
|
||||
|
||||
;===============================================================================
|
||||
; Vectors
|
||||
@ -205,20 +206,20 @@ Portable 65xx Assembler [16.06]
|
||||
.org $ffe0
|
||||
|
||||
00:FFE0 00000000 : .space 4 ; Reserved
|
||||
00:FFE4 18F0 : .word COPN ; $FFE4 - COP(816)
|
||||
00:FFE6 18F0 : .word BRKN ; $FFE6 - BRK(816)
|
||||
00:FFE8 18F0 : .word ABORTN ; $FFE8 - ABORT(816)
|
||||
00:FFEA 18F0 : .word NMIN ; $FFEA - NMI(816)
|
||||
00:FFE4 1AF0 : .word COPN ; $FFE4 - COP(816)
|
||||
00:FFE6 1AF0 : .word BRKN ; $FFE6 - BRK(816)
|
||||
00:FFE8 1AF0 : .word ABORTN ; $FFE8 - ABORT(816)
|
||||
00:FFEA 1AF0 : .word NMIN ; $FFEA - NMI(816)
|
||||
00:FFEC 0000 : .space 2 ; Reserved
|
||||
00:FFEE 18F0 : .word IRQN ; $FFEE - IRQ(816)
|
||||
00:FFEE 1AF0 : .word IRQN ; $FFEE - IRQ(816)
|
||||
|
||||
00:FFF0 00000000 : .space 4
|
||||
00:FFF4 1AF0 : .word COP ; $FFF4 - COP(C02)
|
||||
00:FFF4 1CF0 : .word COP ; $FFF4 - COP(C02)
|
||||
00:FFF6 0000 : .space 2 ; $Reserved
|
||||
00:FFF8 1AF0 : .word ABORT ; $FFF8 - ABORT(C02)
|
||||
00:FFFA 1AF0 : .word NMI ; $FFFA - NMI(C02)
|
||||
00:FFF8 1CF0 : .word ABORT ; $FFF8 - ABORT(C02)
|
||||
00:FFFA 1CF0 : .word NMI ; $FFFA - NMI(C02)
|
||||
00:FFFC 00F0 : .word RESET ; $FFFC - RESET(C02)
|
||||
00:FFFE 1AF0 : .word IRQBRK ; $FFFE - IRQBRK(C02)
|
||||
00:FFFE 1CF0 : .word IRQBRK ; $FFFE - IRQBRK(C02)
|
||||
|
||||
.end
|
||||
|
||||
@ -227,29 +228,29 @@ Portable 65xx Assembler [16.06]
|
||||
|
||||
Symbol Table
|
||||
|
||||
ABORT 0000F01A | __6501__ 00000000
|
||||
ABORTN 0000F018 | __6502__ 00000000
|
||||
BRKN 0000F018 | __65832__ 00000000
|
||||
ABORT 0000F01C | __6501__ 00000000
|
||||
ABORTN 0000F01A | __6502__ 00000000
|
||||
BRKN 0000F01A | __65832__ 00000000
|
||||
B_FLAG 00000010 | __65C02__ 00000000
|
||||
COP 0000F01A | __65SC02__ 00000000
|
||||
COPN 0000F018 | C_FLAG 00000001
|
||||
COP 0000F01C | __65SC02__ 00000000
|
||||
COPN 0000F01A | C_FLAG 00000001
|
||||
C_FLAG 00000001 | __65816__ 00000001
|
||||
D_FLAG 00000008 | Z_FLAG 00000002
|
||||
IRQBRK 0000F01A | I_FLAG 00000004
|
||||
IRQN 0000F018 | D_FLAG 00000008
|
||||
IRQBRK 0000F01C | I_FLAG 00000004
|
||||
IRQN 0000F01A | D_FLAG 00000008
|
||||
I_FLAG 00000004 | B_FLAG 00000010
|
||||
M_FLAG 00000020 | X_FLAG 00000010
|
||||
NMI 0000F01A | M_FLAG 00000020
|
||||
NMIN 0000F018 | V_FLAG 00000040
|
||||
NMI 0000F01C | M_FLAG 00000020
|
||||
NMIN 0000F01A | V_FLAG 00000040
|
||||
N_FLAG 00000080 | N_FLAG 00000080
|
||||
RESET 0000F000 | STACK 00000080'
|
||||
STACK 00000080' | RESET 0000F000
|
||||
V_FLAG 00000040 | ABORTN 0000F018
|
||||
X_FLAG 00000010 | BRKN 0000F018
|
||||
Z_FLAG 00000002 | COPN 0000F018
|
||||
__6501__ 00000000 | IRQN 0000F018
|
||||
__6502__ 00000000 | NMIN 0000F018
|
||||
__65816__ 00000001 | ABORT 0000F01A
|
||||
__65832__ 00000000 | COP 0000F01A
|
||||
__65C02__ 00000000 | IRQBRK 0000F01A
|
||||
__65SC02__ 00000000 | NMI 0000F01A
|
||||
V_FLAG 00000040 | ABORTN 0000F01A
|
||||
X_FLAG 00000010 | BRKN 0000F01A
|
||||
Z_FLAG 00000002 | COPN 0000F01A
|
||||
__6501__ 00000000 | IRQN 0000F01A
|
||||
__6502__ 00000000 | NMIN 0000F01A
|
||||
__65816__ 00000001 | ABORT 0000F01C
|
||||
__65832__ 00000000 | COP 0000F01C
|
||||
__65C02__ 00000000 | IRQBRK 0000F01C
|
||||
__65SC02__ 00000000 | NMI 0000F01C
|
||||
|
@ -5,5 +5,5 @@ Global Symbol Map
|
||||
Sections:
|
||||
|
||||
.page0 : 00000000 - 0000007F in simple.obj
|
||||
.code : 0000F000 - 0000F01B in simple.obj
|
||||
.code : 0000F000 - 0000F01D in simple.obj
|
||||
0000FFE0 - 0000FFFF in simple.obj
|
||||
|
@ -1,4 +1,4 @@
|
||||
S22400F00078D818FBC230A980001BA00200A27B00CAD0FD88D0F742FF80FE80FE0000000070
|
||||
S22400F00078D818FBC230A980001BA06400A20000CAD0FD88D0F742FF80E680FE80FE000023
|
||||
S22400F0200000000000000000000000000000000000000000000000000000000000000000CB
|
||||
S22400F0400000000000000000000000000000000000000000000000000000000000000000AB
|
||||
S22400F06000000000000000000000000000000000000000000000000000000000000000008B
|
||||
@ -125,6 +125,6 @@ S22400FF6000000000000000000000000000000000000000000000000000000000000000007C
|
||||
S22400FF8000000000000000000000000000000000000000000000000000000000000000005C
|
||||
S22400FFA000000000000000000000000000000000000000000000000000000000000000003C
|
||||
S22400FFC000000000000000000000000000000000000000000000000000000000000000001C
|
||||
S22400FFE00000000018F018F018F018F0000018F0000000001AF000001AF01AF000F01AF0BC
|
||||
S22400FFE0000000001AF01AF01AF01AF000001AF0000000001CF000001CF01CF000F01CF0AA
|
||||
S505000000807A
|
||||
S80400F0000B
|
||||
|
37
mem816.cc
37
mem816.cc
@ -9,7 +9,7 @@
|
||||
//
|
||||
// A Portable C++ WDC 65C816 Emulator
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (C)2016 Andrew John Jacobs
|
||||
// Copyright (C),2016 Andrew John Jacobs
|
||||
// All rights reserved.
|
||||
//
|
||||
// This work is made available under the terms of the Creative Commons
|
||||
@ -21,22 +21,33 @@
|
||||
|
||||
#include "mem816.h"
|
||||
|
||||
mem816::Addr mem816::memMask;
|
||||
mem816::Addr mem816::ramSize;
|
||||
|
||||
mem816::Byte *mem816::pRAM;
|
||||
const mem816::Byte *mem816::pROM;
|
||||
|
||||
//==============================================================================
|
||||
|
||||
// Construct a memory area using dynamic allocation
|
||||
mem816::mem816(Addr memMask, Addr ramSize, const Byte *pROM)
|
||||
: memMask(memMask), ramSize(ramSize), pROM(pROM), freeRAM(true)
|
||||
{
|
||||
pRAM = new Byte[ramSize];
|
||||
}
|
||||
|
||||
// Construct a memory area using statically allocated arrays
|
||||
mem816::mem816(Addr memMask, Addr ramSize, Byte *pRAM, const Byte *pROM)
|
||||
: memMask(memMask), ramSize(ramSize), pRAM(pRAM), pROM(pROM), freeRAM(false)
|
||||
// Never used.
|
||||
mem816::mem816()
|
||||
{ }
|
||||
|
||||
// Destory an instance releasing the RAM if allocated.
|
||||
// Never used.
|
||||
mem816::~mem816()
|
||||
{ }
|
||||
|
||||
// Sets up the memory areas using a dynamically allocated array
|
||||
void mem816::setMemory(Addr memMask, Addr ramSize, const Byte *pROM)
|
||||
{
|
||||
if (freeRAM) delete pRAM;
|
||||
setMemory(memMask, ramSize, new Byte[ramSize], pROM);
|
||||
}
|
||||
|
||||
// Sets up the memory area using pre-allocated array
|
||||
void mem816::setMemory(Addr memMask, Addr ramSize, Byte *pRAM, const Byte *pROM)
|
||||
{
|
||||
mem816::memMask = memMask;
|
||||
mem816::ramSize = ramSize;
|
||||
mem816::pRAM = pRAM;
|
||||
mem816::pROM = pROM;
|
||||
}
|
48
mem816.h
48
mem816.h
@ -9,7 +9,7 @@
|
||||
//
|
||||
// A Portable C++ WDC 65C816 Emulator
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (C)2016 Andrew John Jacobs
|
||||
// Copyright (C),2016 Andrew John Jacobs
|
||||
// All rights reserved.
|
||||
//
|
||||
// This work is made available under the terms of the Creative Commons
|
||||
@ -24,15 +24,19 @@
|
||||
|
||||
#include "wdc816.h"
|
||||
|
||||
// The mem816 class defines a set of standard methods for defining and accessing
|
||||
// the emulated memory area.
|
||||
|
||||
class mem816 :
|
||||
public wdc816
|
||||
{
|
||||
public:
|
||||
mem816(Addr memMask, Addr ramSize, const Byte *pROM);
|
||||
mem816(Addr memMask, Addr ramSize, Byte *pRAM, const Byte *pROM);
|
||||
~mem816();
|
||||
// Define the memory areas and sizes
|
||||
static void setMemory (Addr memMask, Addr ramSize, const Byte *pROM);
|
||||
static void setMemory (Addr memMask, Addr ramSize, Byte *pRAM, const Byte *pROM);
|
||||
|
||||
INLINE Byte getByte(Addr ea)
|
||||
// Fetch a byte from memory
|
||||
INLINE static Byte getByte(Addr ea)
|
||||
{
|
||||
if ((ea &= memMask) < ramSize)
|
||||
return (pRAM[ea]);
|
||||
@ -40,35 +44,41 @@ public:
|
||||
return (pROM[ea - ramSize]);
|
||||
}
|
||||
|
||||
INLINE Word getWord(Addr ea)
|
||||
// Fetch a word from memory
|
||||
INLINE static Word getWord(Addr ea)
|
||||
{
|
||||
return (join(getByte(ea + 0), getByte(ea + 1)));
|
||||
return (join(getByte(ea + 0), getByte(ea + 1)));
|
||||
}
|
||||
|
||||
INLINE Addr getAddr(Addr ea)
|
||||
// Fetch a long address from memory
|
||||
INLINE static Addr getAddr(Addr ea)
|
||||
{
|
||||
return (join(getByte(ea + 2), getWord(ea + 0)));
|
||||
}
|
||||
|
||||
INLINE void setByte(Addr ea, Byte data)
|
||||
// Write a byte to memory
|
||||
INLINE static void setByte(Addr ea, Byte data)
|
||||
{
|
||||
if ((ea &= memMask) < ramSize)
|
||||
pRAM[ea] = data;
|
||||
}
|
||||
|
||||
INLINE void setWord(Addr ea, Word data)
|
||||
// Write a word to memory
|
||||
INLINE static void setWord(Addr ea, Word data)
|
||||
{
|
||||
setByte(ea + 0, lo(data));
|
||||
setByte(ea + 1, hi(data));
|
||||
setByte(ea + 0, lo(data));
|
||||
setByte(ea + 1, hi(data));
|
||||
}
|
||||
|
||||
protected:
|
||||
mem816();
|
||||
~mem816();
|
||||
|
||||
private:
|
||||
const Addr memMask;
|
||||
const Addr ramSize;
|
||||
static Addr memMask; // The address mask pattern
|
||||
static Addr ramSize; // The amount of RAM
|
||||
|
||||
Byte *pRAM;
|
||||
const Byte *pROM;
|
||||
|
||||
const bool freeRAM;
|
||||
static Byte *pRAM; // Base of RAM memory array
|
||||
static const Byte *pROM; // Base of ROM memory array
|
||||
};
|
||||
#endif
|
||||
#endif
|
23
program.cc
23
program.cc
@ -40,23 +40,20 @@ using namespace std;
|
||||
#define RAM_SIZE (512 * 1024)
|
||||
#define MEM_MASK (512 * 1024L - 1)
|
||||
|
||||
mem816 mem(MEM_MASK, RAM_SIZE, NULL);
|
||||
emu816 emu(mem);
|
||||
|
||||
bool trace = false;
|
||||
|
||||
//==============================================================================
|
||||
|
||||
// Initialise the emulator
|
||||
void setup()
|
||||
INLINE void setup()
|
||||
{
|
||||
emu.reset(trace);
|
||||
emu816::setMemory(MEM_MASK, RAM_SIZE, NULL);
|
||||
}
|
||||
|
||||
// Execute instructions
|
||||
void loop()
|
||||
INLINE void loop()
|
||||
{
|
||||
emu.step();
|
||||
emu816::step();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@ -108,7 +105,7 @@ void load(char *filename)
|
||||
unsigned long addr = toAddr(line, offset);
|
||||
count -= 4;
|
||||
while (count-- > 0) {
|
||||
mem.setByte(addr++, toByte(line, offset));
|
||||
emu816::setByte(addr++, toByte(line, offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,6 +120,8 @@ int main(int argc, char **argv)
|
||||
{
|
||||
int index = 1;
|
||||
|
||||
setup();
|
||||
|
||||
while (index < argc) {
|
||||
if (argv[index][0] != '-') break;
|
||||
|
||||
@ -155,16 +154,17 @@ int main(int argc, char **argv)
|
||||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&start);
|
||||
|
||||
setup();
|
||||
while (!emu.isStopped ())
|
||||
emu816::reset(trace);
|
||||
while (!emu816::isStopped ())
|
||||
loop();
|
||||
|
||||
QueryPerformanceCounter(&end);
|
||||
|
||||
double secs = (end.QuadPart - start.QuadPart) / (double) freq.QuadPart;
|
||||
|
||||
double speed = emu.getCycles() / secs;
|
||||
double speed = emu816::getCycles() / secs;
|
||||
|
||||
cout << endl << "Executed " << emu816::getCycles() << " in " << secs << " Secs";
|
||||
cout << endl << "Overall CPU Frequency = ";
|
||||
if (speed < 1000.0)
|
||||
cout << speed << " Hz";
|
||||
@ -176,5 +176,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
system("pause");
|
||||
return(0);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
//
|
||||
// A Portable C++ WDC 65C816 Emulator
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (C)2016 Andrew John Jacobs
|
||||
// Copyright (C),2016 Andrew John Jacobs
|
||||
// All rights reserved.
|
||||
//
|
||||
// This work is made available under the terms of the Creative Commons
|
||||
@ -21,9 +21,11 @@
|
||||
|
||||
#include "wdc816.h"
|
||||
|
||||
// Never used.
|
||||
wdc816::wdc816()
|
||||
{ }
|
||||
|
||||
// Never used.
|
||||
wdc816::~wdc816()
|
||||
{ }
|
||||
|
||||
|
22
wdc816.h
22
wdc816.h
@ -9,7 +9,7 @@
|
||||
//
|
||||
// A Portable C++ WDC 65C816 Emulator
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (C)2016 Andrew John Jacobs
|
||||
// Copyright (C),2016 Andrew John Jacobs
|
||||
// All rights reserved.
|
||||
//
|
||||
// This work is made available under the terms of the Creative Commons
|
||||
@ -22,25 +22,23 @@
|
||||
#ifndef WDC816_H
|
||||
#define WDC816_H
|
||||
|
||||
//#define CHIPKIT
|
||||
|
||||
#ifdef CHIPKIT
|
||||
# define INLINE inline
|
||||
#else
|
||||
# define INLINE inline
|
||||
#endif
|
||||
|
||||
// The wdc816 class defines common types for 8-, 16- and 24-bit data values and
|
||||
// a set of common functions for manipulating them.
|
||||
|
||||
class wdc816
|
||||
{
|
||||
public:
|
||||
// Common types for memory and register sizes
|
||||
typedef unsigned char Bit;
|
||||
typedef unsigned char Byte;
|
||||
typedef unsigned short Word;
|
||||
typedef unsigned long Addr;
|
||||
|
||||
wdc816 ();
|
||||
~wdc816();
|
||||
typedef unsigned char Bit;
|
||||
typedef unsigned char Byte;
|
||||
typedef unsigned short Word;
|
||||
typedef unsigned long Addr;
|
||||
|
||||
// Convert a value to a hex string.
|
||||
static char *toHex(unsigned long value, unsigned int digits);
|
||||
@ -80,5 +78,9 @@ public:
|
||||
{
|
||||
return ((value >> 8) | (value << 8));
|
||||
}
|
||||
|
||||
protected:
|
||||
wdc816();
|
||||
~wdc816();
|
||||
};
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user