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