mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
79be6f2355
commit
1a889ae232
|
@ -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/";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
processors += z80
|
||||
processors += tlcs900h z80
|
||||
|
||||
objects += ngp-interface ngp-system
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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) {
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
auto TLCS900H::serialize(serializer& s) -> void {
|
||||
}
|
|
@ -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 = {};
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#define register $register
|
||||
|
||||
#include <nall/intrinsics.hpp>
|
||||
|
||||
namespace Math {
|
||||
|
|
Loading…
Reference in New Issue