Update to v106r71 release.

byuu says:

I started working on the Toshiba TLCS900H CPU core today.

It's basically, "what if we took the Z80, added in 32-bit support, added
in SPARC register windows, added a ton of additional addressing modes,
added control registers, and added a bunch of additional instructions?"
-- or in other words, it's basically hell for me.

It took several hours just to wrap my head around the way the opcode
decoder needed to function, but I think I have a decent strategy for
implementing it now.

I should have all of the first-byte register/memory address decoding in
place, although I'm sure there's lots of bugs. I don't have anything in
the way of a disassembler yet.
This commit is contained in:
Tim Allen 2019-01-05 11:35:26 +11:00
parent 79be6f2355
commit 1a889ae232
14 changed files with 635 additions and 3 deletions

View File

@ -30,7 +30,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "106.70";
static const string Version = "106.71";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "https://byuu.org/";

View File

@ -1,4 +1,4 @@
processors += z80
processors += tlcs900h z80
objects += ngp-interface ngp-system

View File

@ -1,13 +1,14 @@
#pragma once
//license: GPLv3
//started: ...
//started: 2019-01-03
#include <emulator/emulator.hpp>
#include <emulator/thread.hpp>
#include <emulator/scheduler.hpp>
#include <emulator/cheat.hpp>
#include <processor/tlcs900h/tlcs900h.hpp>
#include <processor/z80/z80.hpp>
namespace NeoGeoPocket {

View File

@ -8,6 +8,7 @@ objects += $(if $(findstring lr35902,$(processors)),processor-lr35902)
objects += $(if $(findstring m68k,$(processors)),processor-m68k)
objects += $(if $(findstring mos6502,$(processors)),processor-mos6502)
objects += $(if $(findstring spc700,$(processors)),processor-spc700)
objects += $(if $(findstring tlcs900h,$(processors)),processor-tlcs900h)
objects += $(if $(findstring upd96050,$(processors)),processor-upd96050)
objects += $(if $(findstring v30mz,$(processors)),processor-v30mz)
objects += $(if $(findstring wdc65816,$(processors)),processor-wdc65816)
@ -21,6 +22,7 @@ obj/processor-lr35902.o: processor/lr35902/lr35902.cpp
obj/processor-m68k.o: processor/m68k/m68k.cpp
obj/processor-mos6502.o: processor/mos6502/mos6502.cpp
obj/processor-spc700.o: processor/spc700/spc700.cpp
obj/processor-tlcs900h.o: processor/tlcs900h/tlcs900h.cpp
obj/processor-upd96050.o: processor/upd96050/upd96050.cpp
obj/processor-v30mz.o: processor/v30mz/v30mz.cpp
obj/processor-wdc65816.o: processor/wdc65816/wdc65816.cpp

View File

@ -0,0 +1,32 @@
template<> auto TLCS900H::algorithmAdd<Byte>(uint8 target, uint8 source, uint1 carry) -> uint8 {
uint64 result = target + source + carry;
CF = result.bit(8);
NF = 0;
VF = uint8(~(target ^ source) & (target ^ result)).bit(7);
HF = uint8(target ^ source ^ result).bit(4);
ZF = uint8(result) == 0;
SF = result.bit(7);
return result;
}
template<> auto TLCS900H::algorithmAdd<Word>(uint16 target, uint16 source, uint1 carry) -> uint16 {
uint64 result = target + source + carry;
CF = result.bit(16);
NF = 0;
VF = uint16(~(target ^ source) & (target ^ result)).bit(15);
HF = uint16(target ^ source ^ result).bit(4);
ZF = uint16(result) == 0;
SF = result.bit(15);
return result;
}
template<> auto TLCS900H::algorithmAdd<Long>(uint32 target, uint32 source, uint1 carry) -> uint32 {
uint64 result = target + source + carry;
CF = result.bit(32);
NF = 0;
VF = uint32(~(target ^ source) & (target ^ result)).bit(31);
HF = undefined;
ZF = uint32(result) == 0;
SF = result.bit(31);
return result;
}

View File

@ -0,0 +1,251 @@
auto TLCS900H::instruction() -> void {
auto data = fetch();
static const Register registers[] = {W, A, B, C, D, E, H, L};
Register register;
Memory memory;
switch(data) {
case 0x00: return instructionNoOperation();
case 0x04: return; //undefined
case 0x12: return instructionComplementCarry();
case 0x1f: return; //undefined
case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
memory = {read<Long>(register)};
return instructionSourceMemory<Byte>(memory);
case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
memory = {read<Long>(register) + (int8)fetch()};
return instructionSourceMemory<Byte>(memory);
case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
memory = {read<Long>(register)};
return instructionSourceMemory<Word>(memory);
case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
memory = {read<Long>(register) + (int8)fetch()};
return instructionSourceMemory<Word>(memory);
case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
memory = {read<Long>(register)};
return instructionSourceMemory<Long>(memory);
case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
memory = {read<Long>(register) + (int8)fetch()};
return instructionSourceMemory<Long>(memory);
case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
memory = {read<Long>(register)};
return instructionTargetMemory(memory);
case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
memory = {read<Long>(register) + (int8)fetch()};
return instructionTargetMemory(memory);
case 0xc0:
memory = {fetch< uint8>()};
return instructionSourceMemory<Byte>(memory);
case 0xc1:
memory = {fetch<uint16>()};
return instructionSourceMemory<Byte>(memory);
case 0xc2:
memory = {fetch<uint24>()};
return instructionSourceMemory<Byte>(memory);
case 0xc3:
data = fetch();
memory = {read<Long>(Register{data & ~3})};
if((data & 3) == 1) memory.value += (int16)fetch<uint16>();
if((data & 3) == 2) memory.value += (int8)read<Byte>(Register{fetch()});
if((data & 3) == 3) memory.value += (int16)read<Word>(Register{fetch() & ~1});
return instructionSourceMemory<Byte>(memory);
case 0xc4:
data = fetch();
register = {data & ~3};
if((data & 3) == 0) write<Long>(register, read<Long>(register) - 1);
if((data & 3) == 1) write<Long>(register, read<Long>(register) - 2);
if((data & 3) == 2) write<Long>(register, read<Long>(register) - 4);
memory = {read<Long>(register)};
return instructionSourceMemory<Byte>(memory);
case 0xc5:
data = fetch();
register = {data & ~3};
memory = {read<Long>(register)};
instructionSourceMemory<Byte>(memory);
if((data & 3) == 0) write<Long>(register, read<Long>(register) + 1);
if((data & 3) == 1) write<Long>(register, read<Long>(register) + 2);
if((data & 3) == 2) write<Long>(register, read<Long>(register) + 4);
return;
case 0xc6:
//undefined
return;
case 0xc7:
register = {fetch()};
return instructionRegister<Byte>(register);
case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
register = registers[data & 7];
return instructionRegister<Byte>(register);
case 0xd0:
memory = {fetch< uint8>()};
return instructionSourceMemory<Word>(memory);
case 0xd1:
memory = {fetch<uint16>()};
return instructionSourceMemory<Word>(memory);
case 0xd2:
memory = {fetch<uint24>()};
return instructionSourceMemory<Word>(memory);
case 0xd3:
data = fetch();
memory = {read<Long>(Register{data & ~3})};
if((data & 3) == 1) memory.value += (int16)fetch<uint16>();
if((data & 3) == 2) memory.value += (int8)read<Byte>(Register{fetch()});
if((data & 3) == 3) memory.value += (int16)read<Word>(Register{fetch() & ~1});
return instructionSourceMemory<Word>(memory);
case 0xd4:
data = fetch();
register = {data & ~3};
if((data & 3) == 0) write<Long>(register, read<Long>(register) - 1);
if((data & 3) == 1) write<Long>(register, read<Long>(register) - 2);
if((data & 3) == 2) write<Long>(register, read<Long>(register) - 4);
memory = {read<Long>(register)};
return instructionSourceMemory<Word>(memory);
case 0xd5:
data = fetch();
register = {data & ~3};
memory = {read<Long>(register)};
instructionSourceMemory<Word>(memory);
if((data & 3) == 0) write<Long>(register, read<Long>(register) + 1);
if((data & 3) == 1) write<Long>(register, read<Long>(register) + 2);
if((data & 3) == 2) write<Long>(register, read<Long>(register) + 4);
return;
case 0xd6:
//undefined
return;
case 0xd7:
register = {fetch() & ~1};
return instructionRegister<Word>(register);
case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
register = registers[data & 7];
return instructionRegister<Word>(register);
case 0xe0:
memory = {fetch< uint8>()};
return instructionSourceMemory<Long>(memory);
case 0xe1:
memory = {fetch<uint16>()};
return instructionSourceMemory<Long>(memory);
case 0xe2:
memory = {fetch<uint24>()};
return instructionSourceMemory<Long>(memory);
case 0xe3:
data = fetch();
memory = {read<Long>(Register{data & ~3})};
if((data & 3) == 1) memory.value += (int16)fetch<uint16>();
if((data & 3) == 2) memory.value += (int8)read<Byte>(Register{fetch()});
if((data & 3) == 3) memory.value += (int16)read<Word>(Register{fetch() & ~1});
return instructionSourceMemory<Long>(memory);
case 0xe4:
data = fetch();
register = {data & ~3};
if((data & 3) == 0) write<Long>(register, read<Long>(register) - 1);
if((data & 3) == 1) write<Long>(register, read<Long>(register) - 2);
if((data & 3) == 2) write<Long>(register, read<Long>(register) - 4);
memory = {read<Long>(register)};
return instructionSourceMemory<Long>(memory);
case 0xe5:
data = fetch();
register = {data & ~3};
memory = {read<Long>(register)};
instructionSourceMemory<Long>(memory);
if((data & 3) == 0) write<Long>(register, read<Long>(register) + 1);
if((data & 3) == 1) write<Long>(register, read<Long>(register) + 2);
if((data & 3) == 2) write<Long>(register, read<Long>(register) + 4);
return;
case 0xe6:
//undefined
return;
case 0xe7:
register = {fetch() & ~3};
return instructionRegister<Long>(register);
case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
register = registers[data & 7];
return instructionRegister<Long>(register);
case 0xf0:
memory = {fetch< uint8>()};
return instructionTargetMemory(memory);
case 0xf1:
memory = {fetch<uint16>()};
return instructionTargetMemory(memory);
case 0xf2:
memory = {fetch<uint24>()};
return instructionTargetMemory(memory);
case 0xf3:
data = fetch();
memory = {read<Long>(Register{data & ~3})};
if((data & 3) == 1) memory.value += (int16)fetch<uint16>();
if((data & 3) == 2) memory.value += (int8)read<Byte>(Register{fetch()});
if((data & 3) == 3) memory.value += (int16)read<Word>(Register{fetch() & ~1});
return instructionTargetMemory(memory);
case 0xf4:
data = fetch();
register = {data & ~3};
if((data & 3) == 0) write<Long>(register, read<Long>(register) - 1);
if((data & 3) == 1) write<Long>(register, read<Long>(register) - 2);
if((data & 3) == 2) write<Long>(register, read<Long>(register) - 4);
memory = {read<Long>(register)};
return instructionTargetMemory(memory);
case 0xf5:
data = fetch();
register = {data & ~3};
memory = {read<Long>(register)};
instructionTargetMemory(memory);
if((data & 3) == 0) write<Long>(register, read<Long>(register) + 1);
if((data & 3) == 1) write<Long>(register, read<Long>(register) + 2);
if((data & 3) == 2) write<Long>(register, read<Long>(register) + 4);
return;
case 0xf6: case 0xf7:
//undefined
return;
case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
return instructionSoftwareInterrupt(Immediate{data.bits(0,2)});
}
}
template<typename Size>
auto TLCS900H::instructionRegister(Register input) -> void {
auto data = fetch();
static const Register registers[] = {W, A, B, C, D, E, H, L};
Register register = registers[data.bits(0,2)];
switch(data) {
case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
return instructionAdd<Size>(register, input);
case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
return instructionAddCarry<Size>(register, input);
}
}
template<typename Size>
auto TLCS900H::instructionSourceMemory(Memory input) -> void {
auto data = fetch();
static const Register registers[] = {W, A, B, C, D, E, H, L};
Register register = registers[data.bits(0,2)];
switch(data) {
case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
return instructionAdd<Size>(register, input);
case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
return instructionAddCarry<Size>(register, input);
}
}
auto TLCS900H::instructionTargetMemory(Memory input) -> void {
auto data = fetch();
static const Register registers[] = {W, A, B, C, D, E, H, L};
Register register = registers[data.bits(0,2)];
switch(data) {
}
}

View File

@ -0,0 +1,19 @@
template<typename Size, typename Target, typename Source>
auto TLCS900H::instructionAdd(Target target, Source source) -> void {
write<Size>(target, algorithmAdd<Size>(read<Size>(target), read<Size>(source)));
}
template<typename Size, typename Target, typename Source>
auto TLCS900H::instructionAddCarry(Target target, Source source) -> void {
write<Size>(target, algorithmAdd<Size>(read<Size>(target), read<Size>(source), CF));
}
auto TLCS900H::instructionComplementCarry() -> void {
CF = !CF;
}
auto TLCS900H::instructionNoOperation() -> void {
}
auto TLCS900H::instructionSoftwareInterrupt(Immediate interrupt) -> void {
}

View File

@ -0,0 +1,59 @@
template<> auto TLCS900H::fetch<uint8>() -> uint8 {
return 0x00;
}
template<> auto TLCS900H::fetch<uint16>() -> uint16 {
uint16 data = fetch<uint8>();
return data | fetch<uint8>() << 8;
}
template<> auto TLCS900H::fetch<uint24>() -> uint24 {
uint24 data = fetch<uint8>();
data |= fetch<uint8>() << 8;
return data | fetch<uint8>() << 16;
}
template<> auto TLCS900H::fetch<uint32>() -> uint32 {
uint32 data = fetch<uint8>();
data |= fetch<uint8>() << 8;
data |= fetch<uint8>() << 16;
return data | fetch<uint8>() << 24;
}
template<> auto TLCS900H::read<Byte>(Memory memory) -> uint8 {
uint32 address = memory.value;
return read(address);
}
template<> auto TLCS900H::read<Word>(Memory memory) -> uint16 {
uint32 address = memory.value;
uint16 data = read(address + 0) << 0;
return data | read(address + 1) << 8;
}
template<> auto TLCS900H::read<Long>(Memory memory) -> uint32 {
uint32 address = memory.value;
uint32 data = read(address + 0) << 0;
data |= read(address + 1) << 8;
data |= read(address + 2) << 16;
return data | read(address + 3) << 24;
}
template<> auto TLCS900H::write<Byte>(Memory memory, uint8 data) -> void {
uint32 address = memory.value;
write(address + 0, data >> 0);
}
template<> auto TLCS900H::write<Word>(Memory memory, uint16 data) -> void {
uint32 address = memory.value;
write(address + 0, data >> 0);
write(address + 1, data >> 8);
}
template<> auto TLCS900H::write<Long>(Memory memory, uint32 data) -> void {
uint32 address = memory.value;
write(address + 0, data >> 0);
write(address + 1, data >> 8);
write(address + 2, data >> 16);
write(address + 3, data >> 24);
}

View File

@ -0,0 +1,115 @@
#define PC r.pc.l.l0
#define CF r.sr.f.c
#define NF r.sr.f.n
#define VF r.sr.f.v
#define HF r.sr.f.h
#define ZF r.sr.f.z
#define SF r.sr.f.s
#define RFP r.sr.rfp
#define RFPP r.sr.rfpp
#define IFF r.sr.iff
#define a RFP
#define p RFPP
template<> auto TLCS900H::map<Byte>(Register register) -> maybe<uint8&> {
switch(register.value) {
#define r(id, name) case id: return r.name;
r(RA0, xwa[0].b.b0) r(RW0, xwa[0].b.b1) r(QA0, xwa[0].b.b2) r(QW0, xwa[0].b.b3)
r(RC0, xbc[0].b.b0) r(RB0, xbc[0].b.b1) r(QC0, xbc[0].b.b2) r(QB0, xbc[0].b.b3)
r(RE0, xde[0].b.b0) r(RD0, xde[0].b.b1) r(QE0, xde[0].b.b2) r(QD0, xde[0].b.b3)
r(RL0, xhl[0].b.b0) r(RH0, xhl[0].b.b1) r(QL0, xhl[0].b.b2) r(QH0, xhl[0].b.b3)
r(RA1, xwa[1].b.b0) r(RW1, xwa[1].b.b1) r(QA1, xwa[1].b.b2) r(QW1, xwa[1].b.b3)
r(RC1, xbc[1].b.b0) r(RB1, xbc[1].b.b1) r(QC1, xbc[1].b.b2) r(QB1, xbc[1].b.b3)
r(RE1, xde[1].b.b0) r(RD1, xde[1].b.b1) r(QE1, xde[1].b.b2) r(QD1, xde[1].b.b3)
r(RL1, xhl[1].b.b0) r(RH1, xhl[1].b.b1) r(QL1, xhl[1].b.b2) r(QH1, xhl[1].b.b3)
r(RA2, xwa[2].b.b0) r(RW2, xwa[2].b.b1) r(QA2, xwa[2].b.b2) r(QW2, xwa[2].b.b3)
r(RC2, xbc[2].b.b0) r(RB2, xbc[2].b.b1) r(QC2, xbc[2].b.b2) r(QB2, xbc[2].b.b3)
r(RE2, xde[2].b.b0) r(RD2, xde[2].b.b1) r(QE2, xde[2].b.b2) r(QD2, xde[2].b.b3)
r(RL2, xhl[2].b.b0) r(RH2, xhl[2].b.b1) r(QL2, xhl[2].b.b2) r(QH2, xhl[2].b.b3)
r(RA3, xwa[3].b.b0) r(RW3, xwa[3].b.b1) r(QA3, xwa[3].b.b2) r(QW3, xwa[3].b.b3)
r(RC3, xbc[3].b.b0) r(RB3, xbc[3].b.b1) r(QC3, xbc[3].b.b2) r(QB3, xbc[3].b.b3)
r(RE3, xde[3].b.b0) r(RD3, xde[3].b.b1) r(QE3, xde[3].b.b2) r(QD3, xde[3].b.b3)
r(RL3, xhl[3].b.b0) r(RH3, xhl[3].b.b1) r(QL3, xhl[3].b.b2) r(QH3, xhl[3].b.b3)
r( AP, xwa[p].b.b0) r( WP, xwa[p].b.b1) r(QAP, xwa[p].b.b2) r(QWP, xwa[p].b.b3)
r( CP, xbc[p].b.b0) r( BP, xbc[p].b.b1) r(QCP, xbc[p].b.b2) r(QBP, xbc[p].b.b3)
r( EP, xde[p].b.b0) r( DP, xde[p].b.b1) r(QEP, xde[p].b.b2) r(QDP, xde[p].b.b3)
r( LP, xhl[p].b.b0) r( HP, xhl[p].b.b1) r(QLP, xhl[p].b.b2) r(QHP, xhl[p].b.b3)
r( A, xwa[a].b.b0) r( W, xwa[a].b.b1) r(QA, xwa[a].b.b2) r(QW, xwa[a].b.b3)
r( C, xbc[a].b.b0) r( B, xbc[a].b.b1) r(QC, xbc[a].b.b2) r(QB, xbc[a].b.b3)
r( E, xde[a].b.b0) r( D, xde[a].b.b1) r(QE, xde[a].b.b2) r(QD, xde[a].b.b3)
r( L, xhl[a].b.b0) r( H, xhl[a].b.b1) r(QL, xhl[a].b.b2) r(QH, xhl[a].b.b3)
r(IXL, xix.b.b0) r(IXH, xix.b.b1) r(QIXL, xix.b.b2) r(QIXH, xix.b.b3)
r(IYL, xiy.b.b0) r(IYH, xiy.b.b1) r(QIYL, xiy.b.b2) r(QIYH, xiy.b.b3)
r(IZL, xiz.b.b0) r(IZH, xiz.b.b1) r(QIZL, xiz.b.b2) r(QIZH, xiz.b.b3)
r(SPL, xsp.b.b0) r(SPH, xsp.b.b1) r(QSPL, xsp.b.b2) r(QSPH, xsp.b.b3)
#undef r
}
return nothing;
}
template<> auto TLCS900H::map<Word>(Register register) -> maybe<uint16&> {
switch(register.value) {
#define r(id, name) case id: return r.name;
r(RWA0, xwa[0].w.w0) r(QWA0, xwa[0].w.w1) r(RBC0, xbc[0].w.w0) r(QBC0, xbc[0].w.w1)
r(RDE0, xde[0].w.w0) r(QDE0, xde[0].w.w1) r(RHL0, xhl[0].w.w0) r(QHL0, xhl[0].w.w1)
r(RWA1, xwa[1].w.w0) r(QWA1, xwa[1].w.w1) r(RBC1, xbc[1].w.w0) r(QBC1, xbc[1].w.w1)
r(RDE1, xde[1].w.w0) r(QDE1, xde[1].w.w1) r(RHL1, xhl[1].w.w0) r(QHL1, xhl[1].w.w1)
r(RWA2, xwa[2].w.w0) r(QWA2, xwa[2].w.w1) r(RBC2, xbc[2].w.w0) r(QBC2, xbc[2].w.w1)
r(RDE2, xde[2].w.w0) r(QDE2, xde[2].w.w1) r(RHL2, xhl[2].w.w0) r(QHL2, xhl[2].w.w1)
r(RWA3, xwa[3].w.w0) r(QWA3, xwa[3].w.w1) r(RBC3, xbc[3].w.w0) r(QBC3, xbc[3].w.w1)
r(RDE3, xde[3].w.w0) r(QDE3, xde[3].w.w1) r(RHL3, xhl[3].w.w0) r(QHL3, xhl[3].w.w1)
r( WAP, xwa[p].w.w0) r(QWAP, xwa[p].w.w1) r( BCP, xbc[p].w.w0) r(QBCP, xbc[p].w.w1)
r( DEP, xde[p].w.w0) r(QDEP, xde[p].w.w1) r( HLP, xhl[p].w.w0) r(QHLP, xhl[p].w.w1)
r( WA, xwa[p].w.w0) r(QWA, xwa[p].w.w1) r( BC, xbc[p].w.w0) r(QBC, xbc[p].w.w1)
r( DE, xde[p].w.w0) r(QDE, xde[p].w.w1) r( HL, xhl[p].w.w0) r(QHL, xhl[p].w.w1)
r(IX, xix.w.w0) r(QIX, xix.w.w1) r(IY, xiy.w.w0) r(QIY, xiy.w.w1)
r(IZ, xiz.w.w0) r(QIZ, xiz.w.w1) r(SP, xsp.w.w0) r(QSP, xsp.w.w0)
#undef r
}
return nothing;
}
template<> auto TLCS900H::map<Long>(Register register) -> maybe<uint32&> {
switch(register.value) {
#define r(id, name) case id: return r.name;
r(XWA0, xwa[0].l.l0) r(XBC0, xbc[0].l.l0) r(XDE0, xde[0].l.l0) r(XHL0, xhl[0].l.l0)
r(XWA1, xwa[1].l.l0) r(XBC1, xbc[1].l.l0) r(XDE1, xde[1].l.l0) r(XHL1, xhl[1].l.l0)
r(XWA2, xwa[2].l.l0) r(XBC2, xbc[2].l.l0) r(XDE2, xde[2].l.l0) r(XHL2, xhl[2].l.l0)
r(XWA3, xwa[3].l.l0) r(XBC3, xbc[3].l.l0) r(XDE3, xde[3].l.l0) r(XHL3, xhl[3].l.l0)
r(XWAP, xwa[p].l.l0) r(XBCP, xbc[p].l.l0) r(XDEP, xde[p].l.l0) r(XHLP, xhl[p].l.l0)
r(XWA, xwa[a].l.l0) r(XBC, xbc[a].l.l0) r(XDE, xde[a].l.l0) r(XHL, xhl[a].l.l0)
r(XIX, xix.l.l0) r(XIY, xiy.l.l0) r(XIZ, xiz.l.l0) r(XSP, xsp.l.l0)
#undef r
}
return nothing;
}
#undef a
#undef p
template<> auto TLCS900H::read<Byte>(Register register) -> uint8 {
return map<Byte>(register)(0);
}
template<> auto TLCS900H::read<Word>(Register register) -> uint16 {
return map<Word>(register)(0);
}
template<> auto TLCS900H::read<Long>(Register register) -> uint32 {
return map<Long>(register)(0);
}
template<> auto TLCS900H::write<Byte>(Register register, uint8 data) -> void {
if(auto r = map<Byte>(register)) r() = data;
}
template<> auto TLCS900H::write<Word>(Register register, uint16 data) -> void {
if(auto r = map<Word>(register)) r() = data;
}
template<> auto TLCS900H::write<Long>(Register register, uint32 data) -> void {
if(auto r = map<Word>(register)) r() = data;
}

View File

@ -0,0 +1,2 @@
auto TLCS900H::serialize(serializer& s) -> void {
}

View File

@ -0,0 +1,21 @@
#include <processor/processor.hpp>
#include "tlcs900h.hpp"
namespace Processor {
#define Byte uint8
#define Word uint16
#define Long uint32
#include "registers.cpp"
#include "memory.cpp"
#include "algorithms.cpp"
#include "instruction.cpp"
#include "instructions.cpp"
#include "serialization.cpp"
auto TLCS900H::power() -> void {
r = {};
}
}

View File

@ -0,0 +1,124 @@
//Toshiba TLCS900/H
#pragma once
namespace Processor {
struct TLCS900H {
using Byte = uint8;
using Word = uint16;
using Long = uint32;
struct Register { Byte value; };
struct Memory { Long value; };
struct Immediate { Long value; };
virtual auto read(uint32 address) -> uint8 = 0;
virtual auto write(uint32 address, uint8 data) -> void = 0;
template<typename Size> auto read(Immediate immediate) -> Size { return immediate.value; }
//tlcs900h.cpp
auto power() -> void;
//registers.cpp
template<typename Size> auto map(Register register) -> maybe<Size&>;
template<typename Size> auto read(Register) -> Size;
template<typename Size> auto write(Register, Size data) -> void;
//memory.cpp
template<typename Size = Byte> auto fetch() -> Size;
template<typename Size> auto read(Memory memory) -> Size;
template<typename Size> auto write(Memory memory, Size data) -> void;
//algorithms.cpp
template<typename Size> auto algorithmAdd(Size target, Size source, uint1 carry = 0) -> Size;
//instruction.cpp
auto instruction() -> void;
template<typename Size> auto instructionRegister(Register input) -> void;
template<typename Size> auto instructionSourceMemory(Memory input) -> void;
auto instructionTargetMemory(Memory input) -> void;
//instructions.cpp
template<typename Size, typename Target, typename Source> auto instructionAdd(Target target, Source source) -> void;
template<typename Size, typename Target, typename Source> auto instructionAddCarry(Target target, Source source) -> void;
auto instructionComplementCarry() -> void;
auto instructionNoOperation() -> void;
auto instructionSoftwareInterrupt(Immediate interrupt) -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
struct DataRegister {
union {
struct { Long order_lsb1(l0); } l;
struct { Word order_lsb2(w0, w1); } w;
struct { Byte order_lsb4(b0, b1, b2, b3); } b;
};
};
struct FlagRegister {
uint1 c; //carry
uint1 n; //negative
uint1 v; //overflow / parity
uint1 h; //half carry
uint1 z; //zero
uint1 s; //sign
};
struct StatusRegister {
uint2 rfp; //register file pointer
uint2 rfpp; //register file pointer - 1
uint3 iff = 7; //interrupt mask flip-flop
FlagRegister f;
FlagRegister fp;
};
struct Registers {
DataRegister xwa[4];
DataRegister xbc[4];
DataRegister xde[4];
DataRegister xhl[4];
DataRegister xix;
DataRegister xiy;
DataRegister xiz;
DataRegister xsp;
DataRegister pc;
StatusRegister sr;
} r;
enum : uint {
RA0, RW0, QA0, QW0, RC0, RB0, QC0, QB0, RE0, RD0, QE0, QD0, RL0, RH0, QL0, QH0,
RA1, RW1, QA1, QW1, RC1, RB1, QC1, QB1, RE1, RD1, QE1, QD1, RL1, RH1, QL1, QH1,
RA2, RW2, QA2, QW2, RC2, RB2, QC2, QB2, RE2, RD2, QE2, QD2, RL2, RH2, QL2, QH2,
RA3, RW3, QA3, QW3, RC3, RB3, QC3, QB3, RE3, RD3, QE3, QD3, RL3, RH3, QL3, QH3, SPC = 0xcf, //AP = 0xd0
AP, WP, QAP, QWP, CP, BP, QCP, QBP, EP, DP, QEP, QDP, LP, HP, QLP, QHP,
A, W, QA, QW, C, B, QC, QB, E, D, QE, QD, L, H, QL, QH,
IXL, IXH, QIXL,QIXH,IYL, IYH, QIYL,QIYH,IZL, IZH, QIZL,QIZH,SPL, SPH, QSPL,QSPH,
};
enum : uint {
RWA0 = 0x00, QWA0 = 0x02, RBC0 = 0x04, QBC0 = 0x06, RDE0 = 0x08, QDE0 = 0x0a, RHL0 = 0x0c, QHL0 = 0x0e,
RWA1 = 0x10, QWA1 = 0x12, RBC1 = 0x14, QBC1 = 0x16, RDE1 = 0x18, QDE1 = 0x1a, RHL1 = 0x1c, QHL1 = 0x1e,
RWA2 = 0x20, QWA2 = 0x22, RBC2 = 0x24, QBC2 = 0x26, RDE2 = 0x28, QDE2 = 0x2a, RHL2 = 0x2c, QHL2 = 0x2e,
RWA3 = 0x30, QWA3 = 0x32, RBC3 = 0x34, QBC3 = 0x36, RDE3 = 0x38, QDE3 = 0x3a, RHL3 = 0x3c, QHL3 = 0x3e,
WAP = 0xd0, QWAP = 0xd2, BCP = 0xd4, QBCP = 0xd6, DEP = 0xd8, QDEP = 0xda, HLP = 0xdc, QHLP = 0xde,
WA = 0xe0, QWA = 0xe2, BC = 0xe4, QBC = 0xe6, DE = 0xe8, QDE = 0xea, HL = 0xec, QHL = 0xee,
IX = 0xf0, QIX = 0xf2, IY = 0xf4, QIY = 0xf6, IZ = 0xf8, QIZ = 0xfa, SP = 0xfc, QSP = 0xfe,
};
enum : uint {
XWA0 = 0x00, XBC0 = 0x04, XDE0 = 0x08, XHL0 = 0x0c,
XWA1 = 0x10, XBC1 = 0x14, XDE1 = 0x18, XHL1 = 0x1c,
XWA2 = 0x20, XBC2 = 0x24, XDE2 = 0x28, XHL2 = 0x2c,
XWA3 = 0x30, XBC3 = 0x34, XDE3 = 0x38, XHL3 = 0x3c,
XWAP = 0xd0, XBCP = 0xd4, XDEP = 0xd8, XHLP = 0xdc,
XWA = 0xe0, XBC = 0xe4, XDE = 0xe8, XHL = 0xec,
XIX = 0xf0, XIY = 0xf4, XIZ = 0xf8, XSP = 0xfc,
};
const uint1 undefined = 0;
};
}

View File

@ -4,6 +4,7 @@
#if defined(ENDIAN_LSB)
//little-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x04030201
#define order_lsb1(a) a
#define order_lsb2(a,b) a,b
#define order_lsb3(a,b,c) a,b,c
#define order_lsb4(a,b,c,d) a,b,c,d
@ -11,6 +12,7 @@
#define order_lsb6(a,b,c,d,e,f) a,b,c,d,e,f
#define order_lsb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g
#define order_lsb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h
#define order_msb1(a) a
#define order_msb2(a,b) b,a
#define order_msb3(a,b,c) c,b,a
#define order_msb4(a,b,c,d) d,c,b,a
@ -20,6 +22,7 @@
#define order_msb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a
#elif defined(ENDIAN_MSB)
//big-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x01020304
#define order_lsb1(a) a
#define order_lsb2(a,b) b,a
#define order_lsb3(a,b,c) c,b,a
#define order_lsb4(a,b,c,d) d,c,b,a
@ -27,6 +30,7 @@
#define order_lsb6(a,b,c,d,e,f) f,e,d,c,b,a
#define order_lsb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a
#define order_lsb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a
#define order_msb1(a) a
#define order_msb2(a,b) a,b
#define order_msb3(a,b,c) a,b,c
#define order_msb4(a,b,c,d) a,b,c,d

View File

@ -1,5 +1,7 @@
#pragma once
#define register $register
#include <nall/intrinsics.hpp>
namespace Math {