From 1a889ae232ba8c95e2c6d5231ef3a65301cc4c94 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Sat, 5 Jan 2019 11:35:26 +1100 Subject: [PATCH] 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. --- higan/emulator/emulator.hpp | 2 +- higan/ngp/GNUmakefile | 2 +- higan/ngp/ngp.hpp | 3 +- higan/processor/GNUmakefile | 2 + higan/processor/tlcs900h/algorithms.cpp | 32 +++ higan/processor/tlcs900h/instruction.cpp | 251 +++++++++++++++++++++ higan/processor/tlcs900h/instructions.cpp | 19 ++ higan/processor/tlcs900h/memory.cpp | 59 +++++ higan/processor/tlcs900h/registers.cpp | 115 ++++++++++ higan/processor/tlcs900h/serialization.cpp | 2 + higan/processor/tlcs900h/tlcs900h.cpp | 21 ++ higan/processor/tlcs900h/tlcs900h.hpp | 124 ++++++++++ nall/endian.hpp | 4 + nall/platform.hpp | 2 + 14 files changed, 635 insertions(+), 3 deletions(-) create mode 100644 higan/processor/tlcs900h/algorithms.cpp create mode 100644 higan/processor/tlcs900h/instruction.cpp create mode 100644 higan/processor/tlcs900h/instructions.cpp create mode 100644 higan/processor/tlcs900h/memory.cpp create mode 100644 higan/processor/tlcs900h/registers.cpp create mode 100644 higan/processor/tlcs900h/serialization.cpp create mode 100644 higan/processor/tlcs900h/tlcs900h.cpp create mode 100644 higan/processor/tlcs900h/tlcs900h.hpp diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index aa085241..321de702 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -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/"; diff --git a/higan/ngp/GNUmakefile b/higan/ngp/GNUmakefile index 120852f9..0e5ab8e1 100644 --- a/higan/ngp/GNUmakefile +++ b/higan/ngp/GNUmakefile @@ -1,4 +1,4 @@ -processors += z80 +processors += tlcs900h z80 objects += ngp-interface ngp-system diff --git a/higan/ngp/ngp.hpp b/higan/ngp/ngp.hpp index 654c6488..ed87a3ae 100644 --- a/higan/ngp/ngp.hpp +++ b/higan/ngp/ngp.hpp @@ -1,13 +1,14 @@ #pragma once //license: GPLv3 -//started: ... +//started: 2019-01-03 #include #include #include #include +#include #include namespace NeoGeoPocket { diff --git a/higan/processor/GNUmakefile b/higan/processor/GNUmakefile index 502e9ad8..4c01a103 100644 --- a/higan/processor/GNUmakefile +++ b/higan/processor/GNUmakefile @@ -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 diff --git a/higan/processor/tlcs900h/algorithms.cpp b/higan/processor/tlcs900h/algorithms.cpp new file mode 100644 index 00000000..863cd687 --- /dev/null +++ b/higan/processor/tlcs900h/algorithms.cpp @@ -0,0 +1,32 @@ +template<> auto TLCS900H::algorithmAdd(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(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(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; +} diff --git a/higan/processor/tlcs900h/instruction.cpp b/higan/processor/tlcs900h/instruction.cpp new file mode 100644 index 00000000..97069814 --- /dev/null +++ b/higan/processor/tlcs900h/instruction.cpp @@ -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(register)}; + return instructionSourceMemory(memory); + + case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: + memory = {read(register) + (int8)fetch()}; + return instructionSourceMemory(memory); + + case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: + memory = {read(register)}; + return instructionSourceMemory(memory); + + case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: + memory = {read(register) + (int8)fetch()}; + return instructionSourceMemory(memory); + + case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: + memory = {read(register)}; + return instructionSourceMemory(memory); + + case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: + memory = {read(register) + (int8)fetch()}; + return instructionSourceMemory(memory); + + case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: + memory = {read(register)}; + return instructionTargetMemory(memory); + + case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: + memory = {read(register) + (int8)fetch()}; + return instructionTargetMemory(memory); + + case 0xc0: + memory = {fetch< uint8>()}; + return instructionSourceMemory(memory); + case 0xc1: + memory = {fetch()}; + return instructionSourceMemory(memory); + case 0xc2: + memory = {fetch()}; + return instructionSourceMemory(memory); + case 0xc3: + data = fetch(); + memory = {read(Register{data & ~3})}; + if((data & 3) == 1) memory.value += (int16)fetch(); + if((data & 3) == 2) memory.value += (int8)read(Register{fetch()}); + if((data & 3) == 3) memory.value += (int16)read(Register{fetch() & ~1}); + return instructionSourceMemory(memory); + case 0xc4: + data = fetch(); + register = {data & ~3}; + if((data & 3) == 0) write(register, read(register) - 1); + if((data & 3) == 1) write(register, read(register) - 2); + if((data & 3) == 2) write(register, read(register) - 4); + memory = {read(register)}; + return instructionSourceMemory(memory); + case 0xc5: + data = fetch(); + register = {data & ~3}; + memory = {read(register)}; + instructionSourceMemory(memory); + if((data & 3) == 0) write(register, read(register) + 1); + if((data & 3) == 1) write(register, read(register) + 2); + if((data & 3) == 2) write(register, read(register) + 4); + return; + case 0xc6: + //undefined + return; + case 0xc7: + register = {fetch()}; + return instructionRegister(register); + case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: + register = registers[data & 7]; + return instructionRegister(register); + + case 0xd0: + memory = {fetch< uint8>()}; + return instructionSourceMemory(memory); + case 0xd1: + memory = {fetch()}; + return instructionSourceMemory(memory); + case 0xd2: + memory = {fetch()}; + return instructionSourceMemory(memory); + case 0xd3: + data = fetch(); + memory = {read(Register{data & ~3})}; + if((data & 3) == 1) memory.value += (int16)fetch(); + if((data & 3) == 2) memory.value += (int8)read(Register{fetch()}); + if((data & 3) == 3) memory.value += (int16)read(Register{fetch() & ~1}); + return instructionSourceMemory(memory); + case 0xd4: + data = fetch(); + register = {data & ~3}; + if((data & 3) == 0) write(register, read(register) - 1); + if((data & 3) == 1) write(register, read(register) - 2); + if((data & 3) == 2) write(register, read(register) - 4); + memory = {read(register)}; + return instructionSourceMemory(memory); + case 0xd5: + data = fetch(); + register = {data & ~3}; + memory = {read(register)}; + instructionSourceMemory(memory); + if((data & 3) == 0) write(register, read(register) + 1); + if((data & 3) == 1) write(register, read(register) + 2); + if((data & 3) == 2) write(register, read(register) + 4); + return; + case 0xd6: + //undefined + return; + case 0xd7: + register = {fetch() & ~1}; + return instructionRegister(register); + case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: + register = registers[data & 7]; + return instructionRegister(register); + + case 0xe0: + memory = {fetch< uint8>()}; + return instructionSourceMemory(memory); + case 0xe1: + memory = {fetch()}; + return instructionSourceMemory(memory); + case 0xe2: + memory = {fetch()}; + return instructionSourceMemory(memory); + case 0xe3: + data = fetch(); + memory = {read(Register{data & ~3})}; + if((data & 3) == 1) memory.value += (int16)fetch(); + if((data & 3) == 2) memory.value += (int8)read(Register{fetch()}); + if((data & 3) == 3) memory.value += (int16)read(Register{fetch() & ~1}); + return instructionSourceMemory(memory); + case 0xe4: + data = fetch(); + register = {data & ~3}; + if((data & 3) == 0) write(register, read(register) - 1); + if((data & 3) == 1) write(register, read(register) - 2); + if((data & 3) == 2) write(register, read(register) - 4); + memory = {read(register)}; + return instructionSourceMemory(memory); + case 0xe5: + data = fetch(); + register = {data & ~3}; + memory = {read(register)}; + instructionSourceMemory(memory); + if((data & 3) == 0) write(register, read(register) + 1); + if((data & 3) == 1) write(register, read(register) + 2); + if((data & 3) == 2) write(register, read(register) + 4); + return; + case 0xe6: + //undefined + return; + case 0xe7: + register = {fetch() & ~3}; + return instructionRegister(register); + case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: + register = registers[data & 7]; + return instructionRegister(register); + + case 0xf0: + memory = {fetch< uint8>()}; + return instructionTargetMemory(memory); + case 0xf1: + memory = {fetch()}; + return instructionTargetMemory(memory); + case 0xf2: + memory = {fetch()}; + return instructionTargetMemory(memory); + case 0xf3: + data = fetch(); + memory = {read(Register{data & ~3})}; + if((data & 3) == 1) memory.value += (int16)fetch(); + if((data & 3) == 2) memory.value += (int8)read(Register{fetch()}); + if((data & 3) == 3) memory.value += (int16)read(Register{fetch() & ~1}); + return instructionTargetMemory(memory); + case 0xf4: + data = fetch(); + register = {data & ~3}; + if((data & 3) == 0) write(register, read(register) - 1); + if((data & 3) == 1) write(register, read(register) - 2); + if((data & 3) == 2) write(register, read(register) - 4); + memory = {read(register)}; + return instructionTargetMemory(memory); + case 0xf5: + data = fetch(); + register = {data & ~3}; + memory = {read(register)}; + instructionTargetMemory(memory); + if((data & 3) == 0) write(register, read(register) + 1); + if((data & 3) == 1) write(register, read(register) + 2); + if((data & 3) == 2) write(register, read(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 +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(register, input); + case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: + return instructionAddCarry(register, input); + } +} + +template +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(register, input); + case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: + return instructionAddCarry(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) { + } +} diff --git a/higan/processor/tlcs900h/instructions.cpp b/higan/processor/tlcs900h/instructions.cpp new file mode 100644 index 00000000..a4341e52 --- /dev/null +++ b/higan/processor/tlcs900h/instructions.cpp @@ -0,0 +1,19 @@ +template +auto TLCS900H::instructionAdd(Target target, Source source) -> void { + write(target, algorithmAdd(read(target), read(source))); +} + +template +auto TLCS900H::instructionAddCarry(Target target, Source source) -> void { + write(target, algorithmAdd(read(target), read(source), CF)); +} + +auto TLCS900H::instructionComplementCarry() -> void { + CF = !CF; +} + +auto TLCS900H::instructionNoOperation() -> void { +} + +auto TLCS900H::instructionSoftwareInterrupt(Immediate interrupt) -> void { +} diff --git a/higan/processor/tlcs900h/memory.cpp b/higan/processor/tlcs900h/memory.cpp new file mode 100644 index 00000000..af3d71d0 --- /dev/null +++ b/higan/processor/tlcs900h/memory.cpp @@ -0,0 +1,59 @@ +template<> auto TLCS900H::fetch() -> uint8 { + return 0x00; +} + +template<> auto TLCS900H::fetch() -> uint16 { + uint16 data = fetch(); + return data | fetch() << 8; +} + +template<> auto TLCS900H::fetch() -> uint24 { + uint24 data = fetch(); + data |= fetch() << 8; + return data | fetch() << 16; +} + +template<> auto TLCS900H::fetch() -> uint32 { + uint32 data = fetch(); + data |= fetch() << 8; + data |= fetch() << 16; + return data | fetch() << 24; +} + +template<> auto TLCS900H::read(Memory memory) -> uint8 { + uint32 address = memory.value; + return read(address); +} + +template<> auto TLCS900H::read(Memory memory) -> uint16 { + uint32 address = memory.value; + uint16 data = read(address + 0) << 0; + return data | read(address + 1) << 8; +} + +template<> auto TLCS900H::read(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(Memory memory, uint8 data) -> void { + uint32 address = memory.value; + write(address + 0, data >> 0); +} + +template<> auto TLCS900H::write(Memory memory, uint16 data) -> void { + uint32 address = memory.value; + write(address + 0, data >> 0); + write(address + 1, data >> 8); +} + +template<> auto TLCS900H::write(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); +} diff --git a/higan/processor/tlcs900h/registers.cpp b/higan/processor/tlcs900h/registers.cpp new file mode 100644 index 00000000..d4043d57 --- /dev/null +++ b/higan/processor/tlcs900h/registers.cpp @@ -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(Register register) -> maybe { + 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(Register register) -> maybe { + 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(Register register) -> maybe { + 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(Register register) -> uint8 { + return map(register)(0); +} + +template<> auto TLCS900H::read(Register register) -> uint16 { + return map(register)(0); +} + +template<> auto TLCS900H::read(Register register) -> uint32 { + return map(register)(0); +} + +template<> auto TLCS900H::write(Register register, uint8 data) -> void { + if(auto r = map(register)) r() = data; +} + +template<> auto TLCS900H::write(Register register, uint16 data) -> void { + if(auto r = map(register)) r() = data; +} + +template<> auto TLCS900H::write(Register register, uint32 data) -> void { + if(auto r = map(register)) r() = data; +} diff --git a/higan/processor/tlcs900h/serialization.cpp b/higan/processor/tlcs900h/serialization.cpp new file mode 100644 index 00000000..2bb655b8 --- /dev/null +++ b/higan/processor/tlcs900h/serialization.cpp @@ -0,0 +1,2 @@ +auto TLCS900H::serialize(serializer& s) -> void { +} diff --git a/higan/processor/tlcs900h/tlcs900h.cpp b/higan/processor/tlcs900h/tlcs900h.cpp new file mode 100644 index 00000000..3bff03a2 --- /dev/null +++ b/higan/processor/tlcs900h/tlcs900h.cpp @@ -0,0 +1,21 @@ +#include +#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 = {}; +} + +} diff --git a/higan/processor/tlcs900h/tlcs900h.hpp b/higan/processor/tlcs900h/tlcs900h.hpp new file mode 100644 index 00000000..06b6aae4 --- /dev/null +++ b/higan/processor/tlcs900h/tlcs900h.hpp @@ -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 auto read(Immediate immediate) -> Size { return immediate.value; } + + //tlcs900h.cpp + auto power() -> void; + + //registers.cpp + template auto map(Register register) -> maybe; + template auto read(Register) -> Size; + template auto write(Register, Size data) -> void; + + //memory.cpp + template auto fetch() -> Size; + template auto read(Memory memory) -> Size; + template auto write(Memory memory, Size data) -> void; + + //algorithms.cpp + template auto algorithmAdd(Size target, Size source, uint1 carry = 0) -> Size; + + //instruction.cpp + auto instruction() -> void; + template auto instructionRegister(Register input) -> void; + template auto instructionSourceMemory(Memory input) -> void; + auto instructionTargetMemory(Memory input) -> void; + + //instructions.cpp + template auto instructionAdd(Target target, Source source) -> void; + template 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; +}; + +} diff --git a/nall/endian.hpp b/nall/endian.hpp index f08a7427..7a01b9a1 100644 --- a/nall/endian.hpp +++ b/nall/endian.hpp @@ -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 diff --git a/nall/platform.hpp b/nall/platform.hpp index 71abfb03..a6566220 100644 --- a/nall/platform.hpp +++ b/nall/platform.hpp @@ -1,5 +1,7 @@ #pragma once +#define register $register + #include namespace Math {