mirror of
https://github.com/andrew-jacobs/emu816.git
synced 2024-12-26 20:30:22 +00:00
Initial file import
This commit is contained in:
parent
034280c56e
commit
02dac91274
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.o
|
||||||
|
emu816
|
23
Makefile
Normal file
23
Makefile
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
CPPFLAGS=-O
|
||||||
|
|
||||||
|
all: emu816
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) *.o
|
||||||
|
$(RM) emu816
|
||||||
|
|
||||||
|
emu816: wdc816.o emu816.o mem816.o program.o
|
||||||
|
g++ wdc816.o emu816.o mem816.o program.o -o emu816
|
||||||
|
|
||||||
|
wdc816.o: \
|
||||||
|
wdc816.cc wdc816.h
|
||||||
|
|
||||||
|
emu816.o: \
|
||||||
|
emu816.cc emu816.h wdc816.h mem816.h
|
||||||
|
|
||||||
|
mem816.o: \
|
||||||
|
mem816.cc mem816.h wdc816.h
|
||||||
|
|
||||||
|
program.o: \
|
||||||
|
program.cc emu816.h mem816.h wdc816.h
|
521
emu816.cc
Normal file
521
emu816.cc
Normal file
@ -0,0 +1,521 @@
|
|||||||
|
|
||||||
|
// TODO: decimal mode
|
||||||
|
|
||||||
|
#include "emu816.h"
|
||||||
|
|
||||||
|
#ifdef CHIPKIT
|
||||||
|
#include "WProgram.h"
|
||||||
|
#else
|
||||||
|
# include <iostream>
|
||||||
|
# include <string>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
emu816::emu816(mem816 &mem)
|
||||||
|
: mem(mem)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
emu816::~emu816()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void emu816::reset()
|
||||||
|
{
|
||||||
|
e = 1;
|
||||||
|
pbr = 0x00 << 16;
|
||||||
|
dbr = 0x00 << 16;
|
||||||
|
dp.w = 0x0000;
|
||||||
|
sp.w = 0x0100;
|
||||||
|
pc = mem.getWord(0xfffc);
|
||||||
|
p.b = 0x34;
|
||||||
|
|
||||||
|
interrupted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emu816::step()
|
||||||
|
{
|
||||||
|
// Check for NMI/IRQ
|
||||||
|
|
||||||
|
SHOWPC();
|
||||||
|
|
||||||
|
switch (mem.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;
|
||||||
|
case 0x03: op_ora(am_srel()); break;
|
||||||
|
case 0x04: op_tsb(am_dpag()); break;
|
||||||
|
case 0x05: op_ora(am_dpag()); break;
|
||||||
|
case 0x06: op_asl(am_dpag()); break;
|
||||||
|
case 0x07: op_ora(am_dpil()); break;
|
||||||
|
case 0x08: op_php(am_impl()); break;
|
||||||
|
case 0x09: op_ora(am_immm()); break;
|
||||||
|
case 0x0a: op_asla(am_acc()); break;
|
||||||
|
case 0x0b: op_phd(am_impl()); break;
|
||||||
|
case 0x0c: op_tsb(am_absl()); break;
|
||||||
|
case 0x0d: op_ora(am_absl()); break;
|
||||||
|
case 0x0e: op_asl(am_absl()); break;
|
||||||
|
case 0x0f: op_ora(am_alng()); break;
|
||||||
|
|
||||||
|
case 0x10: op_bpl(am_rela()); break;
|
||||||
|
case 0x11: op_ora(am_dpiy()); break;
|
||||||
|
case 0x12: op_ora(am_dpgi()); break;
|
||||||
|
case 0x13: op_ora(am_sriy()); break;
|
||||||
|
case 0x14: op_trb(am_dpag()); break;
|
||||||
|
case 0x15: op_ora(am_dpgx()); break;
|
||||||
|
case 0x16: op_asl(am_dpgx()); break;
|
||||||
|
case 0x17: op_ora(am_dily()); break;
|
||||||
|
case 0x18: op_clc(am_impl()); break;
|
||||||
|
case 0x19: op_ora(am_absy()); break;
|
||||||
|
case 0x1a: op_inca(am_acc()); break;
|
||||||
|
case 0x1b: op_tcs(am_impl()); break;
|
||||||
|
case 0x1c: op_trb(am_absl()); break;
|
||||||
|
case 0x1d: op_ora(am_absx()); break;
|
||||||
|
case 0x1e: op_asl(am_absx()); break;
|
||||||
|
case 0x1f: op_ora(am_alnx()); break;
|
||||||
|
|
||||||
|
case 0x20: op_jsr(am_absl()); break;
|
||||||
|
case 0x21: op_and(am_dpix()); break;
|
||||||
|
case 0x22: op_jsl(am_alng()); break;
|
||||||
|
case 0x23: op_and(am_srel()); break;
|
||||||
|
case 0x24: op_bit(am_dpag()); break;
|
||||||
|
case 0x25: op_and(am_dpag()); break;
|
||||||
|
case 0x26: op_rol(am_dpag()); break;
|
||||||
|
case 0x27: op_and(am_dpil()); break;
|
||||||
|
case 0x28: op_plp(am_impl()); break;
|
||||||
|
case 0x29: op_and(am_immm()); break;
|
||||||
|
case 0x2a: op_rola(am_acc()); break;
|
||||||
|
case 0x2b: op_pld(am_impl()); break;
|
||||||
|
case 0x2c: op_bit(am_absl()); break;
|
||||||
|
case 0x2d: op_and(am_absl()); break;
|
||||||
|
case 0x2e: op_rol(am_absl()); break;
|
||||||
|
case 0x2f: op_and(am_alng()); break;
|
||||||
|
|
||||||
|
case 0x30: op_bmi(am_rela()); break;
|
||||||
|
case 0x31: op_and(am_dpiy()); break;
|
||||||
|
case 0x32: op_and(am_dpgi()); break;
|
||||||
|
case 0x33: op_and(am_sriy()); break;
|
||||||
|
case 0x34: op_bit(am_dpgx()); break;
|
||||||
|
case 0x35: op_and(am_dpgx()); break;
|
||||||
|
case 0x36: op_rol(am_dpgx()); break;
|
||||||
|
case 0x37: op_and(am_dily()); break;
|
||||||
|
case 0x38: op_sec(am_impl()); break;
|
||||||
|
case 0x39: op_and(am_absy()); break;
|
||||||
|
case 0x3a: op_deca(am_acc()); break;
|
||||||
|
case 0x3b: op_tsc(am_impl()); break;
|
||||||
|
case 0x3c: op_bit(am_absx()); break;
|
||||||
|
case 0x3d: op_and(am_absx()); break;
|
||||||
|
case 0x3e: op_rol(am_absx()); break;
|
||||||
|
case 0x3f: op_and(am_alnx()); break;
|
||||||
|
|
||||||
|
case 0x40: op_rti(am_impl()); break;
|
||||||
|
case 0x41: op_eor(am_dpix()); break;
|
||||||
|
case 0x42: op_wdm(am_immb()); break;
|
||||||
|
case 0x43: op_eor(am_srel()); break;
|
||||||
|
case 0x44: op_mvp(am_immw()); break;
|
||||||
|
case 0x45: op_eor(am_dpag()); break;
|
||||||
|
case 0x46: op_lsr(am_dpag()); break;
|
||||||
|
case 0x47: op_eor(am_dpil()); break;
|
||||||
|
case 0x48: op_pha(am_impl()); break;
|
||||||
|
case 0x49: op_eor(am_immm()); break;
|
||||||
|
case 0x4a: op_lsra(am_impl()); break;
|
||||||
|
case 0x4b: op_phk(am_impl()); break;
|
||||||
|
case 0x4c: op_jmp(am_absl()); break;
|
||||||
|
case 0x4d: op_eor(am_absl()); break;
|
||||||
|
case 0x4e: op_lsr(am_absl()); break;
|
||||||
|
case 0x4f: op_eor(am_alng()); break;
|
||||||
|
|
||||||
|
case 0x50: op_bvc(am_rela()); break;
|
||||||
|
case 0x51: op_eor(am_dpiy()); break;
|
||||||
|
case 0x52: op_eor(am_dpgi()); break;
|
||||||
|
case 0x53: op_eor(am_sriy()); break;
|
||||||
|
case 0x54: op_mvn(am_immw()); break;
|
||||||
|
case 0x55: op_eor(am_dpgx()); break;
|
||||||
|
case 0x56: op_lsr(am_dpgx()); break;
|
||||||
|
case 0x57: op_eor(am_dpil()); break;
|
||||||
|
case 0x58: op_cli(am_impl()); break;
|
||||||
|
case 0x59: op_eor(am_absy()); break;
|
||||||
|
case 0x5a: op_phy(am_impl()); break;
|
||||||
|
case 0x5b: op_tcd(am_impl()); break;
|
||||||
|
case 0x5c: op_jmp(am_alng()); break;
|
||||||
|
case 0x5d: op_eor(am_absx()); break;
|
||||||
|
case 0x5e: op_lsr(am_absx()); break;
|
||||||
|
case 0x5f: op_eor(am_alnx()); break;
|
||||||
|
|
||||||
|
case 0x60: op_rts(am_impl()); break;
|
||||||
|
case 0x61: op_adc(am_dpix()); break;
|
||||||
|
case 0x62: op_per(am_lrel()); break;
|
||||||
|
case 0x63: op_adc(am_srel()); break;
|
||||||
|
case 0x64: op_stz(am_dpag()); break;
|
||||||
|
case 0x65: op_adc(am_dpag()); break;
|
||||||
|
case 0x66: op_ror(am_dpag()); break;
|
||||||
|
case 0x67: op_adc(am_dpil()); break;
|
||||||
|
case 0x68: op_pla(am_impl()); break;
|
||||||
|
case 0x69: op_adc(am_immm()); break;
|
||||||
|
case 0x6a: op_rora(am_impl()); break;
|
||||||
|
case 0x6b: op_rtl(am_impl()); break;
|
||||||
|
case 0x6c: op_jmp(am_absi()); break;
|
||||||
|
case 0x6d: op_adc(am_absl()); break;
|
||||||
|
case 0x6e: op_ror(am_absl()); break;
|
||||||
|
case 0x6f: op_adc(am_alng()); break;
|
||||||
|
|
||||||
|
case 0x70: op_bvs(am_rela()); break;
|
||||||
|
case 0x71: op_adc(am_dpiy()); break;
|
||||||
|
case 0x72: op_adc(am_dpgi()); break;
|
||||||
|
case 0x73: op_adc(am_sriy()); break;
|
||||||
|
case 0x74: op_stz(am_dpgx()); break;
|
||||||
|
case 0x75: op_adc(am_dpgx()); break;
|
||||||
|
case 0x76: op_ror(am_dpgx()); break;
|
||||||
|
case 0x77: op_adc(am_dily()); break;
|
||||||
|
case 0x78: op_sei(am_impl()); break;
|
||||||
|
case 0x79: op_adc(am_absy()); break;
|
||||||
|
case 0x7a: op_ply(am_impl()); break;
|
||||||
|
case 0x7b: op_tdc(am_impl()); break;
|
||||||
|
case 0x7c: op_jmp(am_abxi()); break;
|
||||||
|
case 0x7d: op_adc(am_absx()); break;
|
||||||
|
case 0x7e: op_ror(am_absx()); break;
|
||||||
|
case 0x7f: op_adc(am_alnx()); break;
|
||||||
|
|
||||||
|
case 0x80: op_bra(am_rela()); break;
|
||||||
|
case 0x81: op_sta(am_dpix()); break;
|
||||||
|
case 0x82: op_brl(am_lrel()); break;
|
||||||
|
case 0x83: op_sta(am_srel()); break;
|
||||||
|
case 0x84: op_sty(am_dpag()); break;
|
||||||
|
case 0x85: op_sta(am_dpag()); break;
|
||||||
|
case 0x86: op_stx(am_dpag()); break;
|
||||||
|
case 0x87: op_sta(am_dpil()); break;
|
||||||
|
case 0x88: op_dey(am_impl()); break;
|
||||||
|
case 0x89: op_biti(am_immm()); break;
|
||||||
|
case 0x8a: op_txa(am_impl()); break;
|
||||||
|
case 0x8b: op_phb(am_impl()); break;
|
||||||
|
case 0x8c: op_sty(am_absl()); break;
|
||||||
|
case 0x8d: op_sta(am_absl()); break;
|
||||||
|
case 0x8e: op_stx(am_absl()); break;
|
||||||
|
case 0x8f: op_sta(am_alng()); break;
|
||||||
|
|
||||||
|
case 0x90: op_bcc(am_rela()); break;
|
||||||
|
case 0x91: op_sta(am_dpiy()); break;
|
||||||
|
case 0x92: op_sta(am_dpgi()); break;
|
||||||
|
case 0x93: op_sta(am_sriy()); break;
|
||||||
|
case 0x94: op_sty(am_dpgx()); break;
|
||||||
|
case 0x95: op_sta(am_dpgx()); break;
|
||||||
|
case 0x96: op_stx(am_dpgy()); break;
|
||||||
|
case 0x97: op_sta(am_dily()); break;
|
||||||
|
case 0x98: op_tya(am_impl()); break;
|
||||||
|
case 0x99: op_sta(am_absy()); break;
|
||||||
|
case 0x9a: op_txs(am_impl()); break;
|
||||||
|
case 0x9b: op_txy(am_impl()); break;
|
||||||
|
case 0x9c: op_stz(am_absl()); break;
|
||||||
|
case 0x9d: op_sta(am_absx()); break;
|
||||||
|
case 0x9e: op_stz(am_absx()); break;
|
||||||
|
case 0x9f: op_sta(am_alnx()); break;
|
||||||
|
|
||||||
|
case 0xa0: op_ldy(am_immx()); break;
|
||||||
|
case 0xa1: op_lda(am_dpix()); break;
|
||||||
|
case 0xa2: op_ldx(am_immx()); break;
|
||||||
|
case 0xa3: op_lda(am_srel()); break;
|
||||||
|
case 0xa4: op_ldy(am_dpag()); break;
|
||||||
|
case 0xa5: op_lda(am_dpag()); break;
|
||||||
|
case 0xa6: op_ldx(am_dpag()); break;
|
||||||
|
case 0xa7: op_lda(am_dpil()); break;
|
||||||
|
case 0xa8: op_tay(am_impl()); break;
|
||||||
|
case 0xa9: op_lda(am_immm()); break;
|
||||||
|
case 0xaa: op_tax(am_impl()); break;
|
||||||
|
case 0xab: op_plb(am_impl()); break;
|
||||||
|
case 0xac: op_ldy(am_absl()); break;
|
||||||
|
case 0xad: op_lda(am_absl()); break;
|
||||||
|
case 0xae: op_ldx(am_absl()); break;
|
||||||
|
case 0xaf: op_lda(am_alng()); break;
|
||||||
|
|
||||||
|
case 0xb0: op_bcs(am_rela()); break;
|
||||||
|
case 0xb1: op_lda(am_dpiy()); break;
|
||||||
|
case 0xb2: op_lda(am_dpgi()); break;
|
||||||
|
case 0xb3: op_lda(am_sriy()); break;
|
||||||
|
case 0xb4: op_ldy(am_dpgx()); break;
|
||||||
|
case 0xb5: op_lda(am_dpgx()); break;
|
||||||
|
case 0xb6: op_ldx(am_dpgy()); break;
|
||||||
|
case 0xb7: op_lda(am_dpil()); break;
|
||||||
|
case 0xb8: op_clv(am_impl()); break;
|
||||||
|
case 0xb9: op_lda(am_absy()); break;
|
||||||
|
case 0xba: op_tsx(am_impl()); break;
|
||||||
|
case 0xbb: op_tyx(am_impl()); break;
|
||||||
|
case 0xbc: op_ldy(am_absx()); break;
|
||||||
|
case 0xbd: op_lda(am_absx()); break;
|
||||||
|
case 0xbe: op_ldx(am_absy()); break;
|
||||||
|
case 0xbf: op_lda(am_alng()); break;
|
||||||
|
|
||||||
|
case 0xc0: op_cpy(am_immx()); break;
|
||||||
|
case 0xc1: op_cmp(am_dpix()); break;
|
||||||
|
case 0xc2: op_rep(am_immb()); break;
|
||||||
|
case 0xc3: op_cmp(am_srel()); break;
|
||||||
|
case 0xc4: op_cpy(am_dpag()); break;
|
||||||
|
case 0xc5: op_cmp(am_dpag()); break;
|
||||||
|
case 0xc6: op_dec(am_dpag()); break;
|
||||||
|
case 0xc7: op_cmp(am_dpil()); break;
|
||||||
|
case 0xc8: op_iny(am_impl()); break;
|
||||||
|
case 0xc9: op_cmp(am_immm()); break;
|
||||||
|
case 0xca: op_dex(am_impl()); break;
|
||||||
|
case 0xcb: op_wai(am_impl()); break;
|
||||||
|
case 0xcc: op_cpy(am_absl()); break;
|
||||||
|
case 0xcd: op_cmp(am_absl()); break;
|
||||||
|
case 0xce: op_dec(am_absl()); break;
|
||||||
|
case 0xcf: op_cmp(am_alng()); break;
|
||||||
|
|
||||||
|
case 0xd0: op_bne(am_rela()); break;
|
||||||
|
case 0xd1: op_cmp(am_dpiy()); break;
|
||||||
|
case 0xd2: op_cmp(am_dpgi()); break;
|
||||||
|
case 0xd3: op_cmp(am_sriy()); break;
|
||||||
|
case 0xd4: op_pei(am_dpgi()); break;
|
||||||
|
case 0xd5: op_cmp(am_dpgx()); break;
|
||||||
|
case 0xd6: op_dec(am_dpgx()); break;
|
||||||
|
case 0xd7: op_cmp(am_dily()); break;
|
||||||
|
case 0xd8: op_cld(am_impl()); break;
|
||||||
|
case 0xd9: op_cmp(am_absy()); break;
|
||||||
|
case 0xda: op_phx(am_impl()); break;
|
||||||
|
case 0xdb: op_stp(am_impl()); break;
|
||||||
|
case 0xdc: op_jmp(am_abil()); break;
|
||||||
|
case 0xdd: op_cmp(am_absx()); break;
|
||||||
|
case 0xde: op_dec(am_absx()); break;
|
||||||
|
case 0xdf: op_cmp(am_alnx()); break;
|
||||||
|
|
||||||
|
case 0xe0: op_cpx(am_immx()); break;
|
||||||
|
case 0xe1: op_sbc(am_dpix()); break;
|
||||||
|
case 0xe2: op_sep(am_immb()); break;
|
||||||
|
case 0xe3: op_sbc(am_srel()); break;
|
||||||
|
case 0xe4: op_cpx(am_dpag()); break;
|
||||||
|
case 0xe5: op_sbc(am_dpag()); break;
|
||||||
|
case 0xe6: op_inc(am_dpag()); break;
|
||||||
|
case 0xe7: op_sbc(am_dpil()); break;
|
||||||
|
case 0xe8: op_inx(am_impl()); break;
|
||||||
|
case 0xe9: op_sbc(am_immm()); break;
|
||||||
|
case 0xea: op_nop(am_impl()); break;
|
||||||
|
case 0xeb: op_xba(am_impl()); break;
|
||||||
|
case 0xec: op_cpx(am_absl()); break;
|
||||||
|
case 0xed: op_sbc(am_absl()); break;
|
||||||
|
case 0xee: op_inc(am_absl()); break;
|
||||||
|
case 0xef: op_sbc(am_alng()); break;
|
||||||
|
|
||||||
|
case 0xf0: op_beq(am_rela()); break;
|
||||||
|
case 0xf1: op_sbc(am_dpiy()); break;
|
||||||
|
case 0xf2: op_sbc(am_dpgi()); break;
|
||||||
|
case 0xf3: op_sbc(am_sriy()); break;
|
||||||
|
case 0xf4: op_pea(am_immw()); break;
|
||||||
|
case 0xf5: op_sbc(am_dpgx()); break;
|
||||||
|
case 0xf6: op_inc(am_dpgx()); break;
|
||||||
|
case 0xf7: op_sbc(am_dily()); break;
|
||||||
|
case 0xf8: op_sed(am_impl()); break;
|
||||||
|
case 0xf9: op_sbc(am_absy()); break;
|
||||||
|
case 0xfa: op_plx(am_impl()); break;
|
||||||
|
case 0xfb: op_xce(am_impl()); break;
|
||||||
|
case 0xfc: op_jsr(am_abxi()); break;
|
||||||
|
case 0xfd: op_sbc(am_absx()); break;
|
||||||
|
case 0xfe: op_inc(am_absx()); break;
|
||||||
|
case 0xff: op_sbc(am_alnx()); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENDL();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Debugging Utilities
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef CHIPKIT
|
||||||
|
void emu816::show()
|
||||||
|
{
|
||||||
|
Serial.print (toHex(pbr, 2));
|
||||||
|
Serial.print (':');
|
||||||
|
Serial.print (toHex(pc, 4));
|
||||||
|
Serial.print (' ');
|
||||||
|
Serial.print (toHex(mem.getByte(join(pbr, pc)), 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void emu816::bytes(unsigned int count)
|
||||||
|
{
|
||||||
|
if (count > 0) {
|
||||||
|
Serial.print(' ');
|
||||||
|
Serial.print(toHex(mem.getByte(bank(pbr) | (pc + 0)), 2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Serial.print(" ");
|
||||||
|
|
||||||
|
if (count > 1) {
|
||||||
|
Serial.print(' ');
|
||||||
|
Serial.print(toHex(mem.getByte(bank(pbr) | (pc + 1)), 2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Serial.print(" ");
|
||||||
|
|
||||||
|
if (count > 2) {
|
||||||
|
Serial.print(' ');
|
||||||
|
Serial.print(toHex(mem.getByte(bank(pbr) | (pc + 2)), 2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Serial.print(" ");
|
||||||
|
|
||||||
|
Serial.print(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
void emu816::dump(const char *mnem, Addr ea)
|
||||||
|
{
|
||||||
|
Serial.print(mnem);
|
||||||
|
Serial.print(" {");
|
||||||
|
Serial.print(toHex(ea, 4));
|
||||||
|
Serial.print('}');
|
||||||
|
|
||||||
|
Serial.print(" E=");
|
||||||
|
Serial.print(toHex(e, 1));
|
||||||
|
|
||||||
|
Serial.print(" P=");
|
||||||
|
Serial.print(p.f_n ? 'N' : '.');
|
||||||
|
Serial.print(p.f_v ? 'V' : '.');
|
||||||
|
Serial.print(p.f_m ? 'M' : '.');
|
||||||
|
Serial.print(p.f_x ? 'X' : '.');
|
||||||
|
Serial.print(p.f_d ? 'D' : '.');
|
||||||
|
Serial.print(p.f_i ? 'I' : '.');
|
||||||
|
Serial.print(p.f_z ? 'Z' : '.');
|
||||||
|
Serial.print(p.f_c ? 'C' : '.');
|
||||||
|
|
||||||
|
Serial.print(" A=");
|
||||||
|
if (e || p.f_m) {
|
||||||
|
Serial.print(toHex(hi(a.w), 2));
|
||||||
|
Serial.print('[');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Serial.print('[');
|
||||||
|
Serial.print(toHex(hi(a.w), 2));
|
||||||
|
}
|
||||||
|
Serial.print(toHex(a.b, 2));
|
||||||
|
Serial.print(']');
|
||||||
|
|
||||||
|
Serial.print(" X=");
|
||||||
|
if (e || p.f_x) {
|
||||||
|
Serial.print(toHex(hi(x.w), 2));
|
||||||
|
Serial.print('[');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Serial.print('[');
|
||||||
|
Serial.print(toHex(hi(x.w), 2));
|
||||||
|
}
|
||||||
|
Serial.print(toHex(x.b, 2));
|
||||||
|
Serial.print(']');
|
||||||
|
|
||||||
|
Serial.print(" Y=");
|
||||||
|
if (e || p.f_x) {
|
||||||
|
Serial.print(toHex(hi(y.w), 2));
|
||||||
|
Serial.print('[');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Serial.print('[');
|
||||||
|
Serial.print(toHex(hi(y.w), 2));
|
||||||
|
}
|
||||||
|
Serial.print(toHex(y.b, 2));
|
||||||
|
Serial.print(']');
|
||||||
|
|
||||||
|
Serial.print(" DP=");
|
||||||
|
Serial.print(toHex(dp.w, 4));
|
||||||
|
|
||||||
|
Serial.print(" SP=");
|
||||||
|
if (e) {
|
||||||
|
Serial.print(toHex(hi(sp.w), 2));
|
||||||
|
Serial.print('[');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Serial.print('[');
|
||||||
|
Serial.print(toHex(hi(sp.w), 2));
|
||||||
|
}
|
||||||
|
Serial.print(toHex(sp.b, 2));
|
||||||
|
Serial.print(']');
|
||||||
|
|
||||||
|
Serial.print(" {");
|
||||||
|
Serial.print(' ');
|
||||||
|
Serial.print(toHex(mem.getByte(sp.w + 1), 2));
|
||||||
|
Serial.print(' ');
|
||||||
|
Serial.print(toHex(mem.getByte(sp.w + 2), 2));
|
||||||
|
Serial.print(' ');
|
||||||
|
Serial.print(toHex(mem.getByte(sp.w + 3), 2));
|
||||||
|
Serial.print(' ');
|
||||||
|
Serial.print(toHex(mem.getByte(sp.w + 4), 2));
|
||||||
|
Serial.print(" }");
|
||||||
|
|
||||||
|
Serial.print(" DBR=");
|
||||||
|
Serial.print(toHex(dbr, 2));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void emu816::show()
|
||||||
|
{
|
||||||
|
cout << toHex(pbr, 2);
|
||||||
|
cout << ':' << toHex(pc, 4);
|
||||||
|
cout << ' ' << toHex(mem.getByte(join(pbr, pc)), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void emu816::bytes(unsigned int count)
|
||||||
|
{
|
||||||
|
if (count > 0)
|
||||||
|
cout << ' ' << toHex(mem.getByte(bank(pbr) | (pc + 0)), 2);
|
||||||
|
else
|
||||||
|
cout << " ";
|
||||||
|
|
||||||
|
if (count > 1)
|
||||||
|
cout << ' ' << toHex(mem.getByte(bank(pbr) | (pc + 1)), 2);
|
||||||
|
else
|
||||||
|
cout << " ";
|
||||||
|
|
||||||
|
if (count > 2)
|
||||||
|
cout << ' ' << toHex(mem.getByte(bank(pbr) | (pc + 2)), 2);
|
||||||
|
else
|
||||||
|
cout << " ";
|
||||||
|
|
||||||
|
cout << ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
void emu816::dump(const char *mnem, Addr ea)
|
||||||
|
{
|
||||||
|
cout << mnem << " {" << toHex(ea, 4) << '}';
|
||||||
|
|
||||||
|
cout << " E=" << toHex(e, 1);
|
||||||
|
cout << " P=" <<
|
||||||
|
(p.f_n ? 'N' : '.') <<
|
||||||
|
(p.f_v ? 'V' : '.') <<
|
||||||
|
(p.f_m ? 'M' : '.') <<
|
||||||
|
(p.f_x ? 'X' : '.') <<
|
||||||
|
(p.f_d ? 'D' : '.') <<
|
||||||
|
(p.f_i ? 'I' : '.') <<
|
||||||
|
(p.f_z ? 'Z' : '.') <<
|
||||||
|
(p.f_c ? 'C' : '.');
|
||||||
|
cout << " A=";
|
||||||
|
if (e || p.f_m)
|
||||||
|
cout << toHex(hi(a.w), 2) << '[';
|
||||||
|
else
|
||||||
|
cout << '[' << toHex(hi(a.w), 2);
|
||||||
|
cout << toHex(a.b, 2) << ']';
|
||||||
|
cout << " X=";
|
||||||
|
if (e || p.f_x)
|
||||||
|
cout << toHex(hi(x.w), 2) << '[';
|
||||||
|
else
|
||||||
|
cout << '[' << toHex(hi(x.w), 2);
|
||||||
|
cout << toHex(x.b, 2) << ']';
|
||||||
|
cout << " Y=";
|
||||||
|
if (e || p.f_x)
|
||||||
|
cout << toHex(hi(y.w), 2) << '[';
|
||||||
|
else
|
||||||
|
cout << '[' << toHex(hi(y.w), 2);
|
||||||
|
cout << toHex(y.b, 2) << ']';
|
||||||
|
cout << " DP=" << toHex(dp.w, 4);
|
||||||
|
cout << " SP=";
|
||||||
|
if (e)
|
||||||
|
cout << toHex(hi(sp.w), 2) << '[';
|
||||||
|
else
|
||||||
|
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 << " }";
|
||||||
|
cout << " DBR=" << toHex(dbr, 2);
|
||||||
|
}
|
||||||
|
#endif
|
15
mem816.cc
Normal file
15
mem816.cc
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
#include "mem816.h"
|
||||||
|
|
||||||
|
mem816::mem816(Addr memMask, Addr ramSize, const Byte *pROM)
|
||||||
|
: memMask(memMask), ramSize(ramSize), pROM(pROM)
|
||||||
|
{
|
||||||
|
pRAM = new Byte[ramSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
mem816::mem816(Addr memMask, Addr ramSize, Byte *pRAM, const Byte *pROM)
|
||||||
|
: memMask(memMask), ramSize(ramSize), pRAM (pRAM), pROM(pROM)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
mem816::~mem816()
|
||||||
|
{ }
|
50
mem816.h
Normal file
50
mem816.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef MEM816
|
||||||
|
#define MEM816
|
||||||
|
#include "wdc816.h"
|
||||||
|
|
||||||
|
class mem816 :
|
||||||
|
public wdc816
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
mem816(Addr memMask, Addr ramSize, const Byte *pROM);
|
||||||
|
mem816(Addr memMask, Addr ramSize, Byte *pRAM, const Byte *pROM);
|
||||||
|
~mem816();
|
||||||
|
|
||||||
|
INLINE Byte getByte(Addr ea)
|
||||||
|
{
|
||||||
|
if ((ea &= memMask) < ramSize)
|
||||||
|
return (pRAM[ea]);
|
||||||
|
|
||||||
|
return (pROM[ea - ramSize]);
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE Word getWord(Addr ea)
|
||||||
|
{
|
||||||
|
return (join(getByte(ea + 0), getByte(ea + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE Addr getAddr(Addr ea)
|
||||||
|
{
|
||||||
|
return (join(getByte(ea + 0), getWord(ea + 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE void setByte(Addr ea, Byte data)
|
||||||
|
{
|
||||||
|
if ((ea &= memMask) < ramSize)
|
||||||
|
pRAM[ea] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE void setWord(Addr ea, Word data)
|
||||||
|
{
|
||||||
|
setByte(ea + 0, lo(data));
|
||||||
|
setByte(ea + 1, hi(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Addr memMask;
|
||||||
|
const Addr ramSize;
|
||||||
|
|
||||||
|
Byte *pRAM;
|
||||||
|
const Byte *pROM;
|
||||||
|
};
|
||||||
|
#endif
|
103
program.cc
Normal file
103
program.cc
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#include "mem816.h"
|
||||||
|
#include "emu816.h"
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Memory Definitions and Access
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define RAM_SIZE (384 * 1024)
|
||||||
|
#define ROM_SIZE (128 * 1024L)
|
||||||
|
#define MEM_MASK (512 * 1024L - 1)
|
||||||
|
|
||||||
|
// The ROM area 128K
|
||||||
|
const wdc816::Byte ROM[ROM_SIZE] =
|
||||||
|
{
|
||||||
|
0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
mem816 mem(MEM_MASK, RAM_SIZE, ROM);
|
||||||
|
emu816 emu(mem);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
emu.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
emu.step();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
unsigned int toNybble(char ch)
|
||||||
|
{
|
||||||
|
if ((ch >= '0') && (ch <= '9')) return (ch - '0');
|
||||||
|
if ((ch >= 'A') && (ch <= 'F')) return (ch - 'A' + 10);
|
||||||
|
if ((ch >= 'a') && (ch <= 'f')) return (ch - 'a' + 10);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int toByte(string &str, int &offset)
|
||||||
|
{
|
||||||
|
unsigned int h = toNybble(str[offset++]) << 4;
|
||||||
|
unsigned int l = toNybble(str[offset++]);
|
||||||
|
|
||||||
|
return (h | l);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long toAddr(string &str, int &offset)
|
||||||
|
{
|
||||||
|
unsigned long h = toByte(str, offset) << 16;
|
||||||
|
unsigned long m = toByte(str, offset) << 8;
|
||||||
|
unsigned long l = toByte(str, offset);
|
||||||
|
|
||||||
|
return (h | m | l);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load(char *filename)
|
||||||
|
{
|
||||||
|
ifstream file(filename);
|
||||||
|
string line;
|
||||||
|
|
||||||
|
if (file.is_open()) {
|
||||||
|
cout << ">> Loading S28: " << filename << endl;
|
||||||
|
|
||||||
|
while (!file.eof()) {
|
||||||
|
file >> line;
|
||||||
|
if ((line[0] == 'S') && (line[1] == '2')) {
|
||||||
|
int offset = 2;
|
||||||
|
unsigned int count = toByte(line, offset);
|
||||||
|
unsigned long addr = toAddr(line, offset);
|
||||||
|
count -= 4;
|
||||||
|
while (count-- > 0) {
|
||||||
|
mem.setByte(addr++, toByte(line, offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
for (int index = 1; index < argc;)
|
||||||
|
load(argv[index++]);
|
||||||
|
|
||||||
|
setup();
|
||||||
|
for (;;) loop();
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
20
wdc816.cc
Normal file
20
wdc816.cc
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include "wdc816.h"
|
||||||
|
|
||||||
|
wdc816::wdc816()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
wdc816::~wdc816()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
char *wdc816::toHex(unsigned long value, unsigned int digits)
|
||||||
|
{
|
||||||
|
static char buffer[16];
|
||||||
|
unsigned int offset = sizeof(buffer);;
|
||||||
|
|
||||||
|
buffer[--offset] = 0;
|
||||||
|
while (digits-- > 0) {
|
||||||
|
buffer[--offset] = "0123456789ABCDEF"[value & 0xf];
|
||||||
|
value >>= 4;
|
||||||
|
}
|
||||||
|
return (&(buffer[offset]));
|
||||||
|
}
|
63
wdc816.h
Normal file
63
wdc816.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#ifndef WDC816
|
||||||
|
#define WDC816
|
||||||
|
|
||||||
|
//#define CHIPKIT
|
||||||
|
|
||||||
|
#ifdef CHIPKIT
|
||||||
|
#define INLINE inline
|
||||||
|
#else
|
||||||
|
#define INLINE inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
// Convert a value to a hex string.
|
||||||
|
static char *toHex(unsigned long value, unsigned int digits);
|
||||||
|
|
||||||
|
// Return the low byte of a word
|
||||||
|
INLINE static Byte lo(Word value)
|
||||||
|
{
|
||||||
|
return ((Byte) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the high byte of a word
|
||||||
|
INLINE static Byte hi(Word value)
|
||||||
|
{
|
||||||
|
return (lo(value >> 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the bank number into a address
|
||||||
|
INLINE static Addr bank(Byte b)
|
||||||
|
{
|
||||||
|
return (b << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine two bytes into a word
|
||||||
|
INLINE static Word join(Byte l, Byte h)
|
||||||
|
{
|
||||||
|
return (l | (h << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine a bank and an word into an address
|
||||||
|
INLINE static Addr join(Byte b, Word a)
|
||||||
|
{
|
||||||
|
return (bank(b) | a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap the high and low bytes of a word
|
||||||
|
INLINE static Word swap(Word value)
|
||||||
|
{
|
||||||
|
return ((value >> 8) | (value << 8));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user