Update to v098r19 release.

byuu says:

Changelog:
- added nall/bit-field.hpp
- updated all CPU cores (sans LR35902 due to some complexities) to use
  BitFields instead of bools
- updated as many CPU cores as I could to use BitFields instead of union {
  struct { uint8_t ... }; }; pairs

The speed changes are mostly a wash for this. In some instances,
I noticed a ~2-3% speedup (eg SNES emulation), and in others a 2-3%
slowdown (eg Famicom emulation.) It's within the margin of error, so
it's safe to say it has no impact.

This does give us a lot of new useful things, however:

- no more manual reconstruction of flag values from lots of left shifts
  and ORs
- no more manual deconstruction of flag values from lots of ANDs
- ability to get completely free aliases to flag groups (eg GSU can
  provide alt2, alt1 and also alt (which is alt2,alt1 combined)
- removes the need for the nasty order_lsbN macro hack (eventually will
  make higan 100% endian independent)
- saves us from insane compilers that try and do nasty things with
  alignment on union-structs
- saves us from insane compilers that try to store bit-field bits in
  reverse order
- will allow some really novel new use cases (I'm planning an
  instant-decode ARM opcode function, for instance.)
- reduces code size (we can serialize flag registers in one line instead
  of one for each flag)

However, I probably won't use it for super critical code that's constantly
reading out register values (eg PPU MMIO registers.) I think there we
would end up with a performance penalty.
This commit is contained in:
Tim Allen 2016-06-09 08:26:35 +10:00
parent b08449215a
commit 50420e3dd2
38 changed files with 475 additions and 496 deletions

View File

@ -9,7 +9,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "098.18";
static const string Version = "098.19";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "http://byuu.org/";

View File

@ -27,7 +27,7 @@ auto ARM::arm_opcode(uint32 rm) {
if(exceptionMode() && d == 15 && save) {
cpsr() = spsr();
processor.setMode((Processor::Mode)cpsr().m);
processor.setMode((Processor::Mode)(uint)cpsr().m);
}
}
@ -48,7 +48,7 @@ auto ARM::arm_move_to_status(uint32 rm) {
psr.f = rm & 0x00000040;
psr.t = rm & 0x00000020;
psr.m = rm & 0x0000001f;
if(source == 0) processor.setMode((Processor::Mode)psr.m);
if(source == 0) processor.setMode((Processor::Mode)(uint)psr.m);
}
}
@ -548,7 +548,7 @@ auto ARM::arm_op_move_multiple() {
if(s && (list & 0x8000)) {
if(mode() != Processor::Mode::USR && mode() != Processor::Mode::SYS) {
cpsr() = spsr();
processor.setMode((Processor::Mode)cpsr().m);
processor.setMode((Processor::Mode)(uint)cpsr().m);
}
}
} else {

View File

@ -19,33 +19,24 @@ struct GPR {
};
struct PSR {
inline operator uint32_t() const {
return (n << 31) + (z << 30) + (c << 29) + (v << 28)
+ (i << 7) + (f << 6) + (t << 5) + (m << 0);
}
union {
uint32_t data = 0;
BitField<uint32_t, 31> n; //negative
BitField<uint32_t, 30> z; //zero
BitField<uint32_t, 29> c; //carry
BitField<uint32_t, 28> v; //overflow
BitField<uint32_t, 7> i; //irq
BitField<uint32_t, 6> f; //fiq
BitField<uint32_t, 5> t; //thumb
BitField<uint32_t, 4, 0> m; //mode
};
inline auto operator=(uint32_t d) {
n = d & (1 << 31);
z = d & (1 << 30);
c = d & (1 << 29);
v = d & (1 << 28);
i = d & (1 << 7);
f = d & (1 << 6);
t = d & (1 << 5);
m = d & 31;
return *this;
}
PSR() = default;
PSR(const PSR& value) { data = value.data; }
auto serialize(serializer&) -> void;
bool n = false; //negative
bool z = false; //zero
bool c = false; //carry
bool v = false; //overflow
bool i = false; //irq
bool f = false; //fiq
bool t = false; //thumb
uint m = 0; //mode
inline operator uint() const { return data & 0xf00000ff; }
inline auto& operator=(uint value) { return data = value, *this; }
inline auto& operator=(const PSR& value) { return data = value.data, *this; }
};
struct Pipeline {
@ -125,6 +116,6 @@ alwaysinline auto cpsr() -> PSR& { return processor.cpsr; }
alwaysinline auto spsr() -> PSR& { return *processor.spsr; }
alwaysinline auto carryout() -> bool& { return processor.carryout; }
alwaysinline auto instruction() -> uint32 { return pipeline.execute.instruction; }
alwaysinline auto mode() -> Processor::Mode { return (Processor::Mode)processor.cpsr.m; }
alwaysinline auto privilegedMode() const -> bool { return (Processor::Mode)processor.cpsr.m != Processor::Mode::USR; }
alwaysinline auto exceptionMode() const -> bool { return privilegedMode() && (Processor::Mode)processor.cpsr.m != Processor::Mode::SYS; }
alwaysinline auto mode() -> Processor::Mode { return (Processor::Mode)(uint)processor.cpsr.m; }
alwaysinline auto privilegedMode() const -> bool { return (Processor::Mode)(uint)processor.cpsr.m != Processor::Mode::USR; }
alwaysinline auto exceptionMode() const -> bool { return privilegedMode() && (Processor::Mode)(uint)processor.cpsr.m != Processor::Mode::SYS; }

View File

@ -1,14 +1,3 @@
auto ARM::PSR::serialize(serializer& s) -> void {
s.integer(n);
s.integer(z);
s.integer(c);
s.integer(v);
s.integer(i);
s.integer(f);
s.integer(t);
s.integer(m);
}
auto ARM::serialize(serializer& s) -> void {
s.integer(processor.r0.data);
s.integer(processor.r1.data);
@ -34,26 +23,26 @@ auto ARM::serialize(serializer& s) -> void {
s.integer(processor.fiq.r12.data);
s.integer(processor.fiq.sp.data);
s.integer(processor.fiq.lr.data);
processor.fiq.spsr.serialize(s);
s.integer(processor.fiq.spsr.data);
s.integer(processor.irq.sp.data);
s.integer(processor.irq.lr.data);
processor.irq.spsr.serialize(s);
s.integer(processor.irq.spsr.data);
s.integer(processor.svc.sp.data);
s.integer(processor.svc.lr.data);
processor.svc.spsr.serialize(s);
s.integer(processor.svc.spsr.data);
s.integer(processor.abt.sp.data);
s.integer(processor.abt.lr.data);
processor.abt.spsr.serialize(s);
s.integer(processor.abt.spsr.data);
s.integer(processor.und.sp.data);
s.integer(processor.und.lr.data);
processor.und.spsr.serialize(s);
s.integer(processor.und.spsr.data);
s.integer(processor.pc.data);
processor.cpsr.serialize(s);
s.integer(processor.cpsr.data);
s.integer(processor.carryout);
s.integer(processor.irqline);
@ -68,5 +57,5 @@ auto ARM::serialize(serializer& s) -> void {
s.integer(crash);
processor.setMode((Processor::Mode)cpsr().m);
processor.setMode((Processor::Mode)(uint)cpsr().m);
}

View File

@ -34,39 +34,25 @@ struct Register {
};
struct SFR {
bool irq; //interrupt flag
bool b; //WITH flag
bool ih; //immediate higher 8-bit flag
bool il; //immediate lower 8-bit flag
bool alt2; //ALT2 mode
bool alt1; //ALT2 instruction mode
bool r; //ROM r14 read flag
bool g; //GO flag
bool ov; //overflow flag
bool s; //sign flag
bool cy; //carry flag
bool z; //zero flag
union {
uint16_t data = 0;
BitField<uint16_t, 15> irq; //interrupt flag
BitField<uint16_t, 12> b; //with flag
BitField<uint16_t, 11> ih; //immediate higher 8-bit flag
BitField<uint16_t, 10> il; //immediate lower 8-bit flag
BitField<uint16_t, 9> alt2; //alt2 instruction mode
BitField<uint16_t, 8> alt1; //alt1 instruction mode
BitField<uint16_t, 6> r; //ROM r14 read flag
BitField<uint16_t, 5> g; //go flag
BitField<uint16_t, 4> ov; //overflow flag
BitField<uint16_t, 3> s; //sign flag
BitField<uint16_t, 2> cy; //carry flag
BitField<uint16_t, 1> z; //zero flag
BitField<uint16_t, 9, 8> alt; //instruction mode (composite flag)
};
operator uint() const {
return (irq << 15) | (b << 12) | (ih << 11) | (il << 10) | (alt2 << 9) | (alt1 << 8)
| (r << 6) | (g << 5) | (ov << 4) | (s << 3) | (cy << 2) | (z << 1);
}
auto& operator=(uint data) {
irq = data & 0x8000;
b = data & 0x1000;
ih = data & 0x0800;
il = data & 0x0400;
alt2 = data & 0x0200;
alt1 = data & 0x0100;
r = data & 0x0040;
g = data & 0x0020;
ov = data & 0x0010;
s = data & 0x0008;
cy = data & 0x0004;
z = data & 0x0002;
return *this;
}
inline operator uint() const { return data & 0x9f7e; }
inline auto& operator=(const uint value) { return data = value, *this; }
};
struct SCMR {

View File

@ -7,19 +7,7 @@ auto GSU::serialize(serializer& s) -> void {
s.integer(regs.r[n].modified);
}
s.integer(regs.sfr.irq);
s.integer(regs.sfr.b);
s.integer(regs.sfr.ih);
s.integer(regs.sfr.il);
s.integer(regs.sfr.alt2);
s.integer(regs.sfr.alt1);
s.integer(regs.sfr.r);
s.integer(regs.sfr.g);
s.integer(regs.sfr.ov);
s.integer(regs.sfr.s);
s.integer(regs.sfr.cy);
s.integer(regs.sfr.z);
s.integer(regs.sfr.data);
s.integer(regs.pbr);
s.integer(regs.rombr);
s.integer(regs.rambr);

View File

@ -165,9 +165,9 @@ L op_readpc();
}
}
auto R6502::opi_clear_flag(bool& flag) {
auto R6502::opi_clear_flag(uint bit) {
L op_readpc();
flag = 0;
regs.p &= ~(1 << bit);
}
auto R6502::opi_decrement(uint8& r) {
@ -299,9 +299,9 @@ auto R6502::opi_rmw_zero_page_x(fp op) {
L op_writezp(zp + regs.x, rd);
}
auto R6502::opi_set_flag(bool& flag) {
auto R6502::opi_set_flag(uint bit) {
L op_readpc();
flag = 1;
regs.p |= 1 << bit;
}
auto R6502::opi_shift(fp op) {

View File

@ -64,7 +64,7 @@ I case 0x0c: return opill_nop_absolute();
I case 0x14: return opill_nop_zero_page_x();
case 0x15: return opi_read_zero_page_x(&R6502::opf_ora);
case 0x16: return opi_rmw_zero_page_x(&R6502::opf_asl);
case 0x18: return opi_clear_flag(regs.p.c);
case 0x18: return opi_clear_flag(regs.p.c.bit);
case 0x19: return opi_read_absolute_y(&R6502::opf_ora);
I case 0x1a: return opill_nop_implied();
I case 0x1c: return opill_nop_absolute_x();
@ -86,7 +86,7 @@ I case 0x1c: return opill_nop_absolute_x();
I case 0x34: return opill_nop_zero_page_x();
case 0x35: return opi_read_zero_page_x(&R6502::opf_and);
case 0x36: return opi_rmw_zero_page_x(&R6502::opf_rol);
case 0x38: return opi_set_flag(regs.p.c);
case 0x38: return opi_set_flag(regs.p.c.bit);
case 0x39: return opi_read_absolute_y(&R6502::opf_and);
I case 0x3a: return opill_nop_implied();
I case 0x3c: return opill_nop_absolute_x();
@ -108,7 +108,7 @@ I case 0x44: return opill_nop_zero_page();
I case 0x54: return opill_nop_zero_page_x();
case 0x55: return opi_read_zero_page_x(&R6502::opf_eor);
case 0x56: return opi_rmw_zero_page_x(&R6502::opf_lsr);
case 0x58: return opi_clear_flag(regs.p.i);
case 0x58: return opi_clear_flag(regs.p.i.bit);
case 0x59: return opi_read_absolute_y(&R6502::opf_eor);
I case 0x5a: return opill_nop_implied();
I case 0x5c: return opill_nop_absolute_x();
@ -131,7 +131,7 @@ I case 0x74: return opill_nop_zero_page_x();
case 0x71: return opi_read_indirect_zero_page_y(&R6502::opf_adc);
case 0x75: return opi_read_zero_page_x(&R6502::opf_adc);
case 0x76: return opi_rmw_zero_page_x(&R6502::opf_ror);
case 0x78: return opi_set_flag(regs.p.i);
case 0x78: return opi_set_flag(regs.p.i.bit);
case 0x79: return opi_read_absolute_y(&R6502::opf_adc);
I case 0x7a: return opill_nop_implied();
I case 0x7c: return opill_nop_absolute_x();
@ -175,7 +175,7 @@ I case 0x89: return opill_nop_immediate();
case 0xb4: return opi_read_zero_page_x(&R6502::opf_ldy);
case 0xb5: return opi_read_zero_page_x(&R6502::opf_lda);
case 0xb6: return opi_read_zero_page_y(&R6502::opf_ldx);
case 0xb8: return opi_clear_flag(regs.p.v);
case 0xb8: return opi_clear_flag(regs.p.v.bit);
case 0xb9: return opi_read_absolute_y(&R6502::opf_lda);
case 0xba: return opi_transfer(regs.s, regs.x, 1);
case 0xbc: return opi_read_absolute_x(&R6502::opf_ldy);
@ -198,7 +198,7 @@ I case 0xc2: return opill_nop_immediate();
I case 0xd4: return opill_nop_zero_page_x();
case 0xd5: return opi_read_zero_page_x(&R6502::opf_cmp);
case 0xd6: return opi_rmw_zero_page_x(&R6502::opf_dec);
case 0xd8: return opi_clear_flag(regs.p.d);
case 0xd8: return opi_clear_flag(regs.p.d.bit);
case 0xd9: return opi_read_absolute_y(&R6502::opf_cmp);
I case 0xda: return opill_nop_implied();
I case 0xdc: return opill_nop_absolute_x();
@ -222,7 +222,7 @@ I case 0xeb: return opi_read_immediate(&R6502::opf_sbc);
I case 0xf4: return opill_nop_zero_page_x();
case 0xf5: return opi_read_zero_page_x(&R6502::opf_sbc);
case 0xf6: return opi_rmw_zero_page_x(&R6502::opf_inc);
case 0xf8: return opi_set_flag(regs.p.d);
case 0xf8: return opi_set_flag(regs.p.d.bit);
case 0xf9: return opi_read_absolute_y(&R6502::opf_sbc);
I case 0xfa: return opill_nop_implied();
I case 0xfc: return opill_nop_absolute_x();

View File

@ -60,7 +60,7 @@ struct R6502 {
using fp = auto (R6502::*)() -> void;
auto opi_branch(bool condition);
auto opi_clear_flag(bool& flag);
auto opi_clear_flag(uint bit);
auto opi_decrement(uint8& r);
auto opi_increment(uint8& r);
auto opi_pull(uint8& r);
@ -78,7 +78,7 @@ struct R6502 {
auto opi_rmw_absolute_x(fp);
auto opi_rmw_zero_page(fp);
auto opi_rmw_zero_page_x(fp);
auto opi_set_flag(bool& flag);
auto opi_set_flag(uint bit);
auto opi_shift(fp);
auto opi_store_absolute(uint8& r);
auto opi_store_absolute_x(uint8& r);

View File

@ -1,15 +1,19 @@
struct Flags {
inline operator uint() {
return (n << 7) | (v << 6) | (d << 3) | (i << 2) | (z << 1) | (c << 0);
}
union {
uint8_t data = 0;
BitField<uint8_t, 7> n;
BitField<uint8_t, 6> v;
BitField<uint8_t, 3> d;
BitField<uint8_t, 2> i;
BitField<uint8_t, 1> z;
BitField<uint8_t, 0> c;
};
inline auto operator=(uint8 data) -> Flags& {
n = data & 0x80; v = data & 0x40;
d = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01;
return *this;
}
bool n, v, d, i, z, c;
inline operator uint() { return data; }
inline auto& operator =(uint value) { return data = value, *this; }
inline auto& operator&=(uint value) { return data &= value, *this; }
inline auto& operator|=(uint value) { return data |= value, *this; }
inline auto& operator^=(uint value) { return data ^= value, *this; }
};
struct Registers {
@ -22,7 +26,8 @@ struct Registers {
struct Register16 {
union {
uint16_t w;
struct { uint8_t order_lsb2(l, h); };
BitField<uint16_t, 0, 7> l;
BitField<uint16_t, 8, 15> h;
};
} abs, iabs;

View File

@ -5,12 +5,7 @@ auto R6502::serialize(serializer& s) -> void {
s.integer(regs.x);
s.integer(regs.y);
s.integer(regs.s);
s.integer(regs.p.n);
s.integer(regs.p.v);
s.integer(regs.p.d);
s.integer(regs.p.i);
s.integer(regs.p.z);
s.integer(regs.p.c);
s.integer(regs.p.data);
s.integer(abs.w);
s.integer(iabs.w);

View File

@ -109,7 +109,7 @@ auto R65816::disassemble() -> string {
auto R65816::disassemble(uint24 addr, bool e, bool m, bool x) -> string {
string s;
reg24 pc;
Reg24 pc;
pc.d = addr;
s = {hex(pc, 6), " "};

View File

@ -83,9 +83,19 @@ L ioIRQ();
}
}
auto R65816::op_flag(bool& flag, bool value) {
//auto R65816::op_flag(bool& flag, bool value) {
//L ioIRQ();
// flag = value;
//}
auto R65816::op_set_flag(uint bit) {
L ioIRQ();
flag = value;
r.p |= 1 << bit;
}
auto R65816::op_clear_flag(uint bit) {
L ioIRQ();
r.p &= ~(1 << bit);
}
auto R65816::op_pflag(bool mode) {
@ -99,14 +109,14 @@ E r.p.m = 1, r.p.x = 1;
}
}
auto R65816::op_transfer_b(reg16& from, reg16& to) {
auto R65816::op_transfer_b(Reg16& from, Reg16& to) {
L ioIRQ();
to.l = from.l;
r.p.n = (to.l & 0x80);
r.p.z = (to.l == 0);
}
auto R65816::op_transfer_w(reg16& from, reg16& to) {
auto R65816::op_transfer_w(Reg16& from, Reg16& to) {
L ioIRQ();
to.w = from.w;
r.p.n = (to.w & 0x8000);
@ -139,12 +149,12 @@ E r.s.l = r.x.l;
N r.s.w = r.x.w;
}
auto R65816::op_push_b(reg16& reg) {
auto R65816::op_push_b(Reg16& reg) {
io();
L writeSP(reg.l);
}
auto R65816::op_push_w(reg16& reg) {
auto R65816::op_push_w(Reg16& reg) {
io();
writeSP(reg.h);
L writeSP(reg.l);
@ -172,7 +182,7 @@ auto R65816::op_php() {
L writeSP(r.p);
}
auto R65816::op_pull_b(reg16& reg) {
auto R65816::op_pull_b(Reg16& reg) {
io();
io();
L reg.l = readSP();
@ -180,7 +190,7 @@ L reg.l = readSP();
r.p.z = (reg.l == 0);
}
auto R65816::op_pull_w(reg16& reg) {
auto R65816::op_pull_w(Reg16& reg) {
io();
io();
reg.l = readSP();

View File

@ -118,7 +118,7 @@ L rd.h = readDP(dp + 1);
call(op);
}
auto R65816::op_read_dpr_b(fp op, reg16& reg) {
auto R65816::op_read_dpr_b(fp op, Reg16& reg) {
dp = readPC();
io2();
io();
@ -126,7 +126,7 @@ L rd.l = readDP(dp + reg.w);
call(op);
}
auto R65816::op_read_dpr_w(fp op, reg16& reg) {
auto R65816::op_read_dpr_w(fp op, Reg16& reg) {
dp = readPC();
io2();
io();

View File

@ -1,11 +1,11 @@
auto R65816::op_adjust_imm_b(reg16& reg, int adjust) {
auto R65816::op_adjust_imm_b(Reg16& reg, int adjust) {
L ioIRQ();
reg.l += adjust;
r.p.n = (reg.l & 0x80);
r.p.z = (reg.l == 0);
}
auto R65816::op_adjust_imm_w(reg16& reg, int adjust) {
auto R65816::op_adjust_imm_w(Reg16& reg, int adjust) {
L ioIRQ();
reg.w += adjust;
r.p.n = (reg.w & 0x8000);

View File

@ -1,24 +1,24 @@
auto R65816::op_write_addr_b(reg16& reg) {
auto R65816::op_write_addr_b(Reg16& reg) {
aa.l = readPC();
aa.h = readPC();
L writeDB(aa.w, reg);
}
auto R65816::op_write_addr_w(reg16& reg) {
auto R65816::op_write_addr_w(Reg16& reg) {
aa.l = readPC();
aa.h = readPC();
writeDB(aa.w + 0, reg >> 0);
L writeDB(aa.w + 1, reg >> 8);
}
auto R65816::op_write_addrr_b(reg16& reg, reg16& idx) {
auto R65816::op_write_addrr_b(Reg16& reg, Reg16& idx) {
aa.l = readPC();
aa.h = readPC();
io();
L writeDB(aa.w + idx, reg);
}
auto R65816::op_write_addrr_w(reg16& reg, reg16& idx) {
auto R65816::op_write_addrr_w(Reg16& reg, Reg16& idx) {
aa.l = readPC();
aa.h = readPC();
io();
@ -26,14 +26,14 @@ auto R65816::op_write_addrr_w(reg16& reg, reg16& idx) {
L writeDB(aa.w + idx + 1, reg >> 8);
}
auto R65816::op_write_longr_b(reg16& idx) {
auto R65816::op_write_longr_b(Reg16& idx) {
aa.l = readPC();
aa.h = readPC();
aa.b = readPC();
L writeLong(aa.d + idx, r.a.l);
}
auto R65816::op_write_longr_w(reg16& idx) {
auto R65816::op_write_longr_w(Reg16& idx) {
aa.l = readPC();
aa.h = readPC();
aa.b = readPC();
@ -41,27 +41,27 @@ auto R65816::op_write_longr_w(reg16& idx) {
L writeLong(aa.d + idx + 1, r.a.h);
}
auto R65816::op_write_dp_b(reg16& reg) {
auto R65816::op_write_dp_b(Reg16& reg) {
dp = readPC();
io2();
L writeDP(dp, reg);
}
auto R65816::op_write_dp_w(reg16& reg) {
auto R65816::op_write_dp_w(Reg16& reg) {
dp = readPC();
io2();
writeDP(dp + 0, reg >> 0);
L writeDP(dp + 1, reg >> 8);
}
auto R65816::op_write_dpr_b(reg16& reg, reg16& idx) {
auto R65816::op_write_dpr_b(Reg16& reg, Reg16& idx) {
dp = readPC();
io2();
io();
L writeDP(dp + idx, reg);
}
auto R65816::op_write_dpr_w(reg16& reg, reg16& idx) {
auto R65816::op_write_dpr_w(Reg16& reg, Reg16& idx) {
dp = readPC();
io2();
io();

View File

@ -88,8 +88,8 @@ struct R65816 {
auto op_read_longx_w(fp);
auto op_read_dp_b(fp);
auto op_read_dp_w(fp);
auto op_read_dpr_b(fp, reg16&);
auto op_read_dpr_w(fp, reg16&);
auto op_read_dpr_b(fp, Reg16&);
auto op_read_dpr_w(fp, Reg16&);
auto op_read_idp_b(fp);
auto op_read_idp_w(fp);
auto op_read_idpx_b(fp);
@ -106,16 +106,16 @@ struct R65816 {
auto op_read_isry_w(fp);
//opcode_write.cpp
auto op_write_addr_b(reg16&);
auto op_write_addr_w(reg16&);
auto op_write_addrr_b(reg16&, reg16&);
auto op_write_addrr_w(reg16&, reg16&);
auto op_write_longr_b(reg16&);
auto op_write_longr_w(reg16&);
auto op_write_dp_b(reg16&);
auto op_write_dp_w(reg16&);
auto op_write_dpr_b(reg16&, reg16&);
auto op_write_dpr_w(reg16&, reg16&);
auto op_write_addr_b(Reg16&);
auto op_write_addr_w(Reg16&);
auto op_write_addrr_b(Reg16&, Reg16&);
auto op_write_addrr_w(Reg16&, Reg16&);
auto op_write_longr_b(Reg16&);
auto op_write_longr_w(Reg16&);
auto op_write_dp_b(Reg16&);
auto op_write_dp_w(Reg16&);
auto op_write_dpr_b(Reg16&, Reg16&);
auto op_write_dpr_w(Reg16&, Reg16&);
auto op_sta_idp_b();
auto op_sta_idp_w();
auto op_sta_ildp_b();
@ -132,8 +132,8 @@ struct R65816 {
auto op_sta_isry_w();
//opcode_rmw.cpp
auto op_adjust_imm_b(reg16&, int);
auto op_adjust_imm_w(reg16&, int);
auto op_adjust_imm_b(Reg16&, int);
auto op_adjust_imm_w(Reg16&, int);
auto op_asl_imm_b();
auto op_asl_imm_w();
auto op_lsr_imm_b();
@ -177,22 +177,23 @@ struct R65816 {
auto op_stp();
auto op_wai();
auto op_xce();
auto op_flag(bool& flag, bool value);
auto op_set_flag(uint bit);
auto op_clear_flag(uint bit);
auto op_pflag(bool);
auto op_transfer_b(reg16&, reg16&);
auto op_transfer_w(reg16&, reg16&);
auto op_transfer_b(Reg16&, Reg16&);
auto op_transfer_w(Reg16&, Reg16&);
auto op_tcs();
auto op_tsx_b();
auto op_tsx_w();
auto op_txs();
auto op_push_b(reg16&);
auto op_push_w(reg16&);
auto op_push_b(Reg16&);
auto op_push_w(Reg16&);
auto op_phd();
auto op_phb();
auto op_phk();
auto op_php();
auto op_pull_b(reg16&);
auto op_pull_w(reg16&);
auto op_pull_b(Reg16&);
auto op_pull_w(Reg16&);
auto op_pld();
auto op_plb();
auto op_plp();
@ -207,7 +208,7 @@ struct R65816 {
auto serialize(serializer&) -> void;
Registers r;
reg24 aa, rd;
Reg24 aa, rd;
uint8 sp, dp;
};

View File

@ -1,88 +1,80 @@
struct Flags {
bool n{0};
bool v{0};
bool m{0};
bool x{0};
bool d{0};
bool i{0};
bool z{0};
bool c{0};
union {
uint8_t b = 0;
BitField<uint8_t, 7> n;
BitField<uint8_t, 6> v;
BitField<uint8_t, 5> m;
BitField<uint8_t, 4> x;
BitField<uint8_t, 3> d;
BitField<uint8_t, 2> i;
BitField<uint8_t, 1> z;
BitField<uint8_t, 0> c;
};
inline operator uint() const {
return (n << 7) + (v << 6) + (m << 5) + (x << 4)
+ (d << 3) + (i << 2) + (z << 1) + (c << 0);
}
inline auto operator=(uint8 data) -> uint {
n = data & 0x80; v = data & 0x40; m = data & 0x20; x = data & 0x10;
d = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01;
return data;
}
inline operator uint() const { return b; }
inline auto operator =(uint value) -> uint { return b = value; }
inline auto operator&=(uint value) -> uint { return b &= value; }
inline auto operator|=(uint value) -> uint { return b |= value; }
};
struct reg16 {
struct Reg16 {
union {
uint16_t w = 0;
//BitField<uint16_t, 0, 7> l;
//BitField<uint16_t, 8, 15> h;
struct { uint8_t order_lsb2(l, h); };
BitField<uint16_t, 0, 7> l;
BitField<uint16_t, 8, 15> h;
};
inline operator uint() const { return w; }
inline auto operator =(uint i) -> uint { return w = i; }
inline auto operator |=(uint i) -> uint { return w |= i; }
inline auto operator ^=(uint i) -> uint { return w ^= i; }
inline auto operator &=(uint i) -> uint { return w &= i; }
inline auto operator<<=(uint i) -> uint { return w <<= i; }
inline auto operator>>=(uint i) -> uint { return w >>= i; }
inline auto operator +=(uint i) -> uint { return w += i; }
inline auto operator -=(uint i) -> uint { return w -= i; }
inline auto operator *=(uint i) -> uint { return w *= i; }
inline auto operator /=(uint i) -> uint { return w /= i; }
inline auto operator %=(uint i) -> uint { return w %= i; }
inline auto operator =(uint value) -> uint { return w = value; }
inline auto operator |=(uint value) -> uint { return w |= value; }
inline auto operator ^=(uint value) -> uint { return w ^= value; }
inline auto operator &=(uint value) -> uint { return w &= value; }
inline auto operator<<=(uint value) -> uint { return w <<= value; }
inline auto operator>>=(uint value) -> uint { return w >>= value; }
inline auto operator +=(uint value) -> uint { return w += value; }
inline auto operator -=(uint value) -> uint { return w -= value; }
inline auto operator *=(uint value) -> uint { return w *= value; }
inline auto operator /=(uint value) -> uint { return w /= value; }
inline auto operator %=(uint value) -> uint { return w %= value; }
};
struct reg24 {
struct Reg24 {
union {
uint32_t d = 0;
//BitField<uint32_t, 0, 15> w;
//BitField<uint32_t, 16, 31> wh;
//BitField<uint32_t, 0, 7> l;
//BitField<uint32_t, 8, 15> h;
//BitField<uint32_t, 16, 23> b;
//BitField<uint32_t, 24, 31> bh;
struct { uint16_t order_lsb2(w, wh); };
struct { uint8_t order_lsb4(l, h, b, bh); };
BitField<uint32_t, 0, 7> l;
BitField<uint32_t, 8, 15> h;
BitField<uint32_t, 16, 23> b;
BitField<uint32_t, 0, 15> w;
};
inline operator uint() const { return d; }
inline auto operator =(uint i) -> uint { return d = uclip<24>(i); }
inline auto operator |=(uint i) -> uint { return d = uclip<24>(d | i); }
inline auto operator ^=(uint i) -> uint { return d = uclip<24>(d ^ i); }
inline auto operator &=(uint i) -> uint { return d = uclip<24>(d & i); }
inline auto operator<<=(uint i) -> uint { return d = uclip<24>(d << i); }
inline auto operator>>=(uint i) -> uint { return d = uclip<24>(d >> i); }
inline auto operator +=(uint i) -> uint { return d = uclip<24>(d + i); }
inline auto operator -=(uint i) -> uint { return d = uclip<24>(d - i); }
inline auto operator *=(uint i) -> uint { return d = uclip<24>(d * i); }
inline auto operator /=(uint i) -> uint { return d = uclip<24>(d / i); }
inline auto operator %=(uint i) -> uint { return d = uclip<24>(d % i); }
inline auto operator =(uint value) -> uint { return d = uint24( value); }
inline auto operator |=(uint value) -> uint { return d = uint24(d | value); }
inline auto operator ^=(uint value) -> uint { return d = uint24(d ^ value); }
inline auto operator &=(uint value) -> uint { return d = uint24(d & value); }
inline auto operator<<=(uint value) -> uint { return d = uint24(d << value); }
inline auto operator>>=(uint value) -> uint { return d = uint24(d >> value); }
inline auto operator +=(uint value) -> uint { return d = uint24(d + value); }
inline auto operator -=(uint value) -> uint { return d = uint24(d - value); }
inline auto operator *=(uint value) -> uint { return d = uint24(d * value); }
inline auto operator /=(uint value) -> uint { return d = uint24(d / value); }
inline auto operator %=(uint value) -> uint { return d = uint24(d % value); }
};
struct Registers {
reg24 pc;
reg16 a;
reg16 x;
reg16 y;
reg16 z; //pseudo-register (zero register)
reg16 s;
reg16 d;
Reg24 pc;
Reg16 a;
Reg16 x;
Reg16 y;
Reg16 z; //pseudo-register (zero register)
Reg16 s;
Reg16 d;
Flags p;
uint8 db{0};
bool e{0};
uint8 db = 0;
bool e = false;
bool irq{0}; //IRQ pin (0 = low, 1 = trigger)
bool wai{0}; //raised during wai, cleared after interrupt triggered
uint8 mdr{0}; //memory data register
uint16 vector{0}; //interrupt vector address
bool irq = false; //IRQ pin (0 = low, 1 = trigger)
bool wai = false; //raised during wai, cleared after interrupt triggered
uint8 mdr = 0; //memory data register
uint16 vector = 0; //interrupt vector address
};

View File

@ -8,14 +8,7 @@ auto R65816::serialize(serializer& s) -> void {
s.integer(r.s.w);
s.integer(r.d.w);
s.integer(r.p.n);
s.integer(r.p.v);
s.integer(r.p.m);
s.integer(r.p.x);
s.integer(r.p.d);
s.integer(r.p.i);
s.integer(r.p.z);
s.integer(r.p.c);
s.integer(r.p.b);
s.integer(r.db);
s.integer(r.e);

View File

@ -38,7 +38,7 @@ auto R65816::instruction() -> void {
opMFI(0x15, read_dpr, ora, r.x)
opMF (0x16, adjust_dpx, asl)
opMF (0x17, read_ildpy, ora)
opAII(0x18, flag, r.p.c, 0)
opAI (0x18, clear_flag, r.p.c.bit)
opMF (0x19, read_addry, ora)
opMII(0x1a, adjust_imm, r.a, +1)
opA (0x1b, tcs)
@ -70,7 +70,7 @@ auto R65816::instruction() -> void {
opMFI(0x35, read_dpr, and, r.x)
opMF (0x36, adjust_dpx, rol)
opMF (0x37, read_ildpy, and)
opAII(0x38, flag, r.p.c, 1)
opAI (0x38, set_flag, r.p.c.bit)
opMF (0x39, read_addry, and)
opMII(0x3a, adjust_imm, r.a, -1)
opAII(0x3b, transfer_w, r.s, r.a)
@ -102,7 +102,7 @@ auto R65816::instruction() -> void {
opMFI(0x55, read_dpr, eor, r.x)
opMF (0x56, adjust_dpx, lsr)
opMF (0x57, read_ildpy, eor)
opAII(0x58, flag, r.p.i, 0)
opAI (0x58, clear_flag, r.p.i.bit)
opMF (0x59, read_addry, eor)
opXI (0x5a, push, r.y)
opAII(0x5b, transfer_w, r.a, r.d)
@ -134,7 +134,7 @@ auto R65816::instruction() -> void {
opMFI(0x75, read_dpr, adc, r.x)
opMF (0x76, adjust_dpx, ror)
opMF (0x77, read_ildpy, adc)
opAII(0x78, flag, r.p.i, 1)
opAI (0x78, set_flag, r.p.i.bit)
opMF (0x79, read_addry, adc)
opXI (0x7a, pull, r.y)
opAII(0x7b, transfer_w, r.d, r.a)
@ -198,7 +198,7 @@ auto R65816::instruction() -> void {
opMFI(0xb5, read_dpr, lda, r.x)
opXFI(0xb6, read_dpr, ldx, r.y)
opMF (0xb7, read_ildpy, lda)
opAII(0xb8, flag, r.p.v, 0)
opAI (0xb8, clear_flag, r.p.v.bit)
opMF (0xb9, read_addry, lda)
opX (0xba, tsx)
opXII(0xbb, transfer, r.y, r.x)
@ -230,7 +230,7 @@ auto R65816::instruction() -> void {
opMFI(0xd5, read_dpr, cmp, r.x)
opMF (0xd6, adjust_dpx, dec)
opMF (0xd7, read_ildpy, cmp)
opAII(0xd8, flag, r.p.d, 0)
opAI (0xd8, clear_flag, r.p.d.bit)
opMF (0xd9, read_addry, cmp)
opXI (0xda, push, r.x)
opA (0xdb, stp)
@ -262,7 +262,7 @@ auto R65816::instruction() -> void {
opMFI(0xf5, read_dpr, sbc, r.x)
opMF (0xf6, adjust_dpx, inc)
opMF (0xf7, read_ildpy, sbc)
opAII(0xf8, flag, r.p.d, 1)
opAI (0xf8, set_flag, r.p.d.bit)
opMF (0xf9, read_addry, sbc)
opXI (0xfa, pull, r.x)
opA (0xfb, xce)

View File

@ -1,6 +1,6 @@
#define call (this->*op)
auto SPC700::op_adjust(fps op, uint8_t& r) {
auto SPC700::op_adjust(fps op, reg r) {
io();
r = call(r);
}
@ -57,7 +57,7 @@ auto SPC700::op_branch_bit() {
regs.pc += (int8)rd;
}
auto SPC700::op_pull(uint8_t& r) {
auto SPC700::op_pull(reg r) {
io();
io();
r = readSP();
@ -69,14 +69,14 @@ auto SPC700::op_push(uint8 r) {
writeSP(r);
}
auto SPC700::op_read_addr(fpb op, uint8_t& r) {
auto SPC700::op_read_addr(fpb op, reg r) {
dp.l = readPC();
dp.h = readPC();
rd = read(dp);
r = call(r, rd);
}
auto SPC700::op_read_addri(fpb op, uint8_t& r) {
auto SPC700::op_read_addri(fpb op, reg r) {
dp.l = readPC();
dp.h = readPC();
io();
@ -84,18 +84,18 @@ auto SPC700::op_read_addri(fpb op, uint8_t& r) {
regs.a = call(regs.a, rd);
}
auto SPC700::op_read_const(fpb op, uint8_t& r) {
auto SPC700::op_read_const(fpb op, reg r) {
rd = readPC();
r = call(r, rd);
}
auto SPC700::op_read_dp(fpb op, uint8_t& r) {
auto SPC700::op_read_dp(fpb op, reg r) {
dp = readPC();
rd = readDP(dp);
r = call(r, rd);
}
auto SPC700::op_read_dpi(fpb op, uint8_t& r, uint8_t& i) {
auto SPC700::op_read_dpi(fpb op, reg r, reg i) {
dp = readPC();
io();
rd = readDP(dp + i);
@ -175,10 +175,10 @@ auto SPC700::op_set_bit() {
writeDP(dp, rd | (!(opcode & 0x10) << (opcode >> 5)));
}
auto SPC700::op_set_flag(bool& flag, bool data) {
auto SPC700::op_set_flag(uint bit, bool value) {
io();
if(&flag == &regs.p.i) io();
flag = data;
if(bit == regs.p.i.bit) io();
regs.p = value ? (regs.p | (1 << bit)) : (regs.p & ~(1 << bit));
}
auto SPC700::op_test_addr(bool set) {
@ -191,7 +191,7 @@ auto SPC700::op_test_addr(bool set) {
write(dp, set ? rd | regs.a : rd & ~regs.a);
}
auto SPC700::op_transfer(uint8_t& from, uint8_t& to) {
auto SPC700::op_transfer(reg from, reg to) {
io();
to = from;
if(&to == &regs.s) return;
@ -199,14 +199,14 @@ auto SPC700::op_transfer(uint8_t& from, uint8_t& to) {
regs.p.z = (to == 0);
}
auto SPC700::op_write_addr(uint8_t& r) {
auto SPC700::op_write_addr(reg r) {
dp.l = readPC();
dp.h = readPC();
read(dp);
write(dp, r);
}
auto SPC700::op_write_addri(uint8_t& i) {
auto SPC700::op_write_addri(reg i) {
dp.l = readPC();
dp.h = readPC();
io();
@ -215,13 +215,13 @@ auto SPC700::op_write_addri(uint8_t& i) {
write(dp, regs.a);
}
auto SPC700::op_write_dp(uint8_t& r) {
auto SPC700::op_write_dp(reg r) {
dp = readPC();
readDP(dp);
writeDP(dp, r);
}
auto SPC700::op_write_dpi(uint8_t& r, uint8_t& i) {
auto SPC700::op_write_dpi(reg r, reg i) {
dp = readPC() + i;
io();
readDP(dp);

View File

@ -1,51 +1,53 @@
struct Flag {
inline operator uint() const {
return (n << 7) | (v << 6) | (p << 5) | (b << 4)
| (h << 3) | (i << 2) | (z << 1) | (c << 0);
}
inline auto operator=(uint data) -> uint {
n = data & 0x80; v = data & 0x40; p = data & 0x20; b = data & 0x10;
h = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01;
return data;
}
inline auto operator|=(uint data) -> uint { return operator=(operator uint() | data); }
inline auto operator^=(uint data) -> uint { return operator=(operator uint() ^ data); }
inline auto operator&=(uint data) -> uint { return operator=(operator uint() & data); }
bool n, v, p, b, h, i, z, c;
};
struct Word {
inline operator uint() const { return w; }
inline auto operator=(uint data) -> uint { return w = data; }
inline auto operator++() -> uint { return ++w; }
inline auto operator--() -> uint { return --w; }
inline auto operator++(int) -> uint { uint data = w++; return data; }
inline auto operator--(int) -> uint { uint data = w--; return data; }
inline auto operator+=(uint data) -> uint { return w += data;; }
inline auto operator-=(uint data) -> uint { return w -= data;; }
inline auto operator|=(uint data) -> uint { return w |= data; }
inline auto operator^=(uint data) -> uint { return w ^= data; }
inline auto operator&=(uint data) -> uint { return w &= data; }
struct Flags {
union {
uint16_t w;
struct { uint8_t order_lsb2(l, h); };
uint8_t data = 0;
BitField<uint8_t, 7> n;
BitField<uint8_t, 6> v;
BitField<uint8_t, 5> p;
BitField<uint8_t, 4> b;
BitField<uint8_t, 3> h;
BitField<uint8_t, 2> i;
BitField<uint8_t, 1> z;
BitField<uint8_t, 0> c;
};
inline operator uint() const { return data; }
inline auto& operator =(uint value) { return data = value, *this; }
inline auto& operator&=(uint value) { return data &= value, *this; }
inline auto& operator|=(uint value) { return data |= value, *this; }
inline auto& operator^=(uint value) { return data ^= value, *this; }
};
struct Regs {
Word pc;
struct Register {
union {
uint16_t w = 0;
BitField<uint16_t, 0, 7> l;
BitField<uint16_t, 8, 15> h;
};
inline operator uint() const { return w; }
inline auto operator=(const Register& value) { w = value.w; }
inline auto operator++(int) { uint value = w++; return value; }
inline auto operator--(int) { uint value = w--; return value; }
inline auto& operator++() { return ++w, *this; }
inline auto& operator--() { return --w, *this; }
inline auto& operator =(uint value) { return w = value, *this; }
inline auto& operator&=(uint value) { return w &= value, *this; }
inline auto& operator|=(uint value) { return w |= value, *this; }
inline auto& operator^=(uint value) { return w ^= value, *this; }
inline auto& operator+=(uint value) { return w += value, *this; }
inline auto& operator-=(uint value) { return w -= value, *this; }
};
struct Registers {
Register pc;
union {
uint16_t ya;
struct { uint8_t order_lsb2(a, y); };
};
uint8_t x, s;
Flag p;
Flags p;
};

View File

@ -4,14 +4,7 @@ auto SPC700::serialize(serializer& s) -> void {
s.integer(regs.x);
s.integer(regs.y);
s.integer(regs.s);
s.integer(regs.p.n);
s.integer(regs.p.v);
s.integer(regs.p.p);
s.integer(regs.p.b);
s.integer(regs.p.h);
s.integer(regs.p.i);
s.integer(regs.p.z);
s.integer(regs.p.c);
s.integer(regs.p.data);
s.integer(opcode);
s.integer(dp.w);

View File

@ -45,7 +45,7 @@ auto SPC700::instruction() -> void {
op(0x1d, adjust, fp(dec), regs.x)
op(0x1e, read_addr, fp(cmp), regs.x)
op(0x1f, jmp_iaddrx)
op(0x20, set_flag, regs.p.p, 0)
op(0x20, set_flag, regs.p.p.bit, 0)
op(0x21, jst)
op(0x22, set_bit)
op(0x23, branch_bit)
@ -77,7 +77,7 @@ auto SPC700::instruction() -> void {
op(0x3d, adjust, fp(inc), regs.x)
op(0x3e, read_dp, fp(cmp), regs.x)
op(0x3f, jsr_addr)
op(0x40, set_flag, regs.p.p, 1)
op(0x40, set_flag, regs.p.p.bit, 1)
op(0x41, jst)
op(0x42, set_bit)
op(0x43, branch_bit)
@ -109,7 +109,7 @@ auto SPC700::instruction() -> void {
op(0x5d, transfer, regs.a, regs.x)
op(0x5e, read_addr, fp(cmp), regs.y)
op(0x5f, jmp_addr)
op(0x60, set_flag, regs.p.c, 0)
op(0x60, set_flag, regs.p.c.bit, 0)
op(0x61, jst)
op(0x62, set_bit)
op(0x63, branch_bit)
@ -141,7 +141,7 @@ auto SPC700::instruction() -> void {
op(0x7d, transfer, regs.x, regs.a)
op(0x7e, read_dp, fp(cmp), regs.y)
op(0x7f, rti)
op(0x80, set_flag, regs.p.c, 1)
op(0x80, set_flag, regs.p.c.bit, 1)
op(0x81, jst)
op(0x82, set_bit)
op(0x83, branch_bit)
@ -173,7 +173,7 @@ auto SPC700::instruction() -> void {
op(0x9d, transfer, regs.s, regs.x)
op(0x9e, div_ya_x)
op(0x9f, xcn)
op(0xa0, set_flag, regs.p.i, 1)
op(0xa0, set_flag, regs.p.i.bit, 1)
op(0xa1, jst)
op(0xa2, set_bit)
op(0xa3, branch_bit)
@ -205,7 +205,7 @@ auto SPC700::instruction() -> void {
op(0xbd, transfer, regs.x, regs.s)
op(0xbe, das)
op(0xbf, lda_ixinc)
op(0xc0, set_flag, regs.p.i, 0)
op(0xc0, set_flag, regs.p.i.bit, 0)
op(0xc1, jst)
op(0xc2, set_bit)
op(0xc3, branch_bit)

View File

@ -17,14 +17,15 @@ struct SPC700 {
#include "registers.hpp"
#include "memory.hpp"
Regs regs;
Word dp, sp, rd, wr, bit, ya;
Registers regs;
Register dp, sp, rd, wr, bit, ya;
uint8 opcode;
protected:
using fps = auto (SPC700::*)(uint8) -> uint8;
using fpb = auto (SPC700::*)(uint8, uint8) -> uint8;
using fpw = auto (SPC700::*)(uint16, uint16) -> uint16;
using reg = uint8_t&;
auto op_adc(uint8, uint8) -> uint8;
auto op_and(uint8, uint8) -> uint8;
@ -45,33 +46,33 @@ protected:
auto op_ldw(uint16, uint16) -> uint16;
auto op_sbw(uint16, uint16) -> uint16;
auto op_adjust(fps, uint8_t&);
auto op_adjust(fps, reg);
auto op_adjust_addr(fps);
auto op_adjust_dp(fps);
auto op_adjust_dpw(int);
auto op_adjust_dpx(fps);
auto op_branch(bool);
auto op_branch_bit();
auto op_pull(uint8_t&);
auto op_pull(reg);
auto op_push(uint8);
auto op_read_addr(fpb, uint8_t&);
auto op_read_addri(fpb, uint8_t&);
auto op_read_const(fpb, uint8_t&);
auto op_read_dp(fpb, uint8_t&);
auto op_read_dpi(fpb, uint8_t&, uint8_t&);
auto op_read_addr(fpb, reg);
auto op_read_addri(fpb, reg);
auto op_read_const(fpb, reg);
auto op_read_dp(fpb, reg);
auto op_read_dpi(fpb, reg, reg);
auto op_read_dpw(fpw);
auto op_read_idpx(fpb);
auto op_read_idpy(fpb);
auto op_read_ix(fpb);
auto op_set_addr_bit();
auto op_set_bit();
auto op_set_flag(bool&, bool);
auto op_set_flag(uint, bool);
auto op_test_addr(bool);
auto op_transfer(uint8_t&, uint8_t&);
auto op_write_addr(uint8_t&);
auto op_write_addri(uint8_t&);
auto op_write_dp(uint8_t&);
auto op_write_dpi(uint8_t&, uint8_t&);
auto op_transfer(reg, reg);
auto op_write_addr(reg);
auto op_write_addri(reg);
auto op_write_dp(reg);
auto op_write_dpi(reg, reg);
auto op_write_dp_const(fpb);
auto op_write_dp_dp(fpb);
auto op_write_ix_iy(fpb);

View File

@ -1,21 +0,0 @@
uPD96050::Flag::operator uint() const {
return (s1 << 5) + (s0 << 4) + (c << 3) + (z << 2) + (ov1 << 1) + (ov0 << 0);
}
auto uPD96050::Flag::operator=(uint d) -> uint {
s1 = d & 0x20; s0 = d & 0x10; c = d & 0x08; z = d & 0x04; ov1 = d & 0x02; ov0 = d & 0x01;
return d;
}
uPD96050::Status::operator uint() const {
return (rqm << 15) + (usf1 << 14) + (usf0 << 13) + (drs << 12)
+ (dma << 11) + (drc << 10) + (soc << 9) + (sic << 8)
+ (ei << 7) + (p1 << 1) + (p0 << 0);
}
auto uPD96050::Status::operator=(uint d) -> uint {
rqm = d & 0x8000; usf1 = d & 0x4000; usf0 = d & 0x2000; drs = d & 0x1000;
dma = d & 0x0800; drc = d & 0x0400; soc = d & 0x0200; sic = d & 0x0100;
ei = d & 0x0080; p1 = d & 0x0002; p0 = d & 0x0001;
return d;
}

View File

@ -14,35 +14,13 @@ auto uPD96050::serialize(serializer& s) -> void {
s.integer(regs.a);
s.integer(regs.b);
s.integer(regs.flaga.s1);
s.integer(regs.flaga.s0);
s.integer(regs.flaga.c);
s.integer(regs.flaga.z);
s.integer(regs.flaga.ov1);
s.integer(regs.flaga.ov0);
s.integer(regs.flagb.s1);
s.integer(regs.flagb.s0);
s.integer(regs.flagb.c);
s.integer(regs.flagb.z);
s.integer(regs.flagb.ov1);
s.integer(regs.flagb.ov0);
s.integer(regs.flaga.data);
s.integer(regs.flagb.data);
s.integer(regs.tr);
s.integer(regs.trb);
s.integer(regs.sr.rqm);
s.integer(regs.sr.usf1);
s.integer(regs.sr.usf0);
s.integer(regs.sr.drs);
s.integer(regs.sr.dma);
s.integer(regs.sr.drc);
s.integer(regs.sr.soc);
s.integer(regs.sr.sic);
s.integer(regs.sr.ei);
s.integer(regs.sr.p1);
s.integer(regs.sr.p0);
s.integer(regs.sr.data);
s.integer(regs.dr);
s.integer(regs.si);
s.integer(regs.so);

View File

@ -3,7 +3,6 @@
namespace Processor {
#include "registers.cpp"
#include "instructions.cpp"
#include "memory.cpp"
#include "disassembler.cpp"

View File

@ -32,19 +32,40 @@ struct uPD96050 {
uint16 dataROM[2048];
uint16 dataRAM[2048];
//registers.cpp
struct Flag {
inline operator uint() const;
inline auto operator=(uint d) -> uint;
union {
uint8_t data = 0;
BitField<uint8_t, 5> s1;
BitField<uint8_t, 4> s0;
BitField<uint8_t, 3> c;
BitField<uint8_t, 2> z;
BitField<uint8_t, 1> ov1;
BitField<uint8_t, 0> ov0;
};
bool s1, s0, c, z, ov1, ov0;
inline operator uint() const { return data & 0x3f; }
inline auto& operator=(uint value) { return data = value, *this; }
inline auto& operator=(const Flag& value) { return data = value.data, *this; }
};
struct Status {
inline operator uint() const;
inline auto operator=(uint d) -> uint;
union {
uint16_t data = 0;
BitField<uint16_t, 15> rqm;
BitField<uint16_t, 14> usf1;
BitField<uint16_t, 13> usf0;
BitField<uint16_t, 12> drs;
BitField<uint16_t, 11> dma;
BitField<uint16_t, 10> drc;
BitField<uint16_t, 9> soc;
BitField<uint16_t, 8> sic;
BitField<uint16_t, 7> ei;
BitField<uint16_t, 1> p1;
BitField<uint16_t, 0> p0;
};
bool rqm, usf1, usf0, drs, dma, drc, soc, sic, ei, p1, p0;
inline operator uint() const { return data & 0xff83; }
inline auto& operator=(uint value) { return data = value, *this; }
};
struct Regs {

View File

@ -16,13 +16,13 @@ auto V30MZ::opComplementCarry() {
r.f.c = !r.f.c;
}
auto V30MZ::opClearFlag(bool& flag) {
auto V30MZ::opClearFlag(uint bit) {
wait(3);
flag = false;
r.f &= ~(1 << bit);
}
auto V30MZ::opSetFlag(bool& flag) {
auto V30MZ::opSetFlag(uint bit) {
wait(3);
flag = true;
if(&flag == &r.f.i) state.poll = false;
r.f |= 1 << bit;
if(bit == r.f.i.bit) state.poll = false;
}

View File

@ -28,26 +28,3 @@ auto V30MZ::setAcc(Size size, uint32 data) -> void {
if(size == Word) r.ax = data;
if(size == Long) r.ax = data, r.dx = data >> 16;
}
//
V30MZ::Registers::Flags::operator uint16_t() const {
return m << 15 | 1 << 14 | 1 << 13 | 1 << 12
| v << 11 | d << 10 | i << 9 | b << 8
| s << 7 | z << 6 | h << 4 | p << 2
| 1 << 1 | c << 0;
}
auto V30MZ::Registers::Flags::operator=(uint16_t data) {
m = (uint1)(data >> 15);
v = (uint1)(data >> 11);
d = (uint1)(data >> 10);
i = (uint1)(data >> 9);
b = (uint1)(data >> 8);
s = (uint1)(data >> 7);
z = (uint1)(data >> 6);
h = (uint1)(data >> 4);
p = (uint1)(data >> 2);
c = (uint1)(data >> 0);
return *this;
}

View File

@ -38,14 +38,5 @@ auto V30MZ::serialize(serializer& s) -> void {
s.integer(r.ss);
s.integer(r.ds);
s.integer(r.ip);
s.integer(r.f.m);
s.integer(r.f.v);
s.integer(r.f.d);
s.integer(r.f.i);
s.integer(r.f.b);
s.integer(r.f.s);
s.integer(r.f.z);
s.integer(r.f.h);
s.integer(r.f.p);
s.integer(r.f.c);
s.integer(r.f.data);
}

View File

@ -333,12 +333,12 @@ auto V30MZ::instruction() -> void {
case 0xf5: return opComplementCarry();
case 0xf6: return opGroup3MemImm(Byte);
case 0xf7: return opGroup3MemImm(Word);
case 0xf8: return opClearFlag(r.f.c);
case 0xf9: return opSetFlag(r.f.c);
case 0xfa: return opClearFlag(r.f.i);
case 0xfb: return opSetFlag(r.f.i);
case 0xfc: return opClearFlag(r.f.d);
case 0xfd: return opSetFlag(r.f.d);
case 0xf8: return opClearFlag(r.f.c.bit);
case 0xf9: return opSetFlag(r.f.c.bit);
case 0xfa: return opClearFlag(r.f.i.bit);
case 0xfb: return opSetFlag(r.f.i.bit);
case 0xfc: return opClearFlag(r.f.d.bit);
case 0xfd: return opSetFlag(r.f.d.bit);
case 0xfe: return opGroup4MemImm(Byte);
case 0xff: return opGroup4MemImm(Word);
}

View File

@ -156,8 +156,8 @@ struct V30MZ {
auto opStoreFlagsAcc();
auto opLoadAccFlags();
auto opComplementCarry();
auto opClearFlag(bool&);
auto opSetFlag(bool&);
auto opClearFlag(uint);
auto opSetFlag(uint);
//instructions-group.cpp
auto opGroup1MemImm(Size, bool);
@ -247,20 +247,25 @@ struct V30MZ {
uint16_t* s[8]{&es, &cs, &ss, &ds, &es, &cs, &ss, &ds};
struct Flags {
//registers.cpp
operator uint16_t() const;
auto operator=(uint16_t data);
union {
uint16_t data = 0;
BitField<uint16_t, 15> m; //mode
BitField<uint16_t, 11> v; //overflow
BitField<uint16_t, 10> d; //direction
BitField<uint16_t, 9> i; //interrupt
BitField<uint16_t, 8> b; //break
BitField<uint16_t, 7> s; //sign
BitField<uint16_t, 6> z; //zero
BitField<uint16_t, 4> h; //half-carry
BitField<uint16_t, 2> p; //parity
BitField<uint16_t, 0> c; //carry
};
bool m; //mode
bool v; //overflow
bool d; //direction
bool i; //interrupt
bool b; //break
bool s; //sign
bool z; //zero
bool h; //half-carry
bool p; //parity
bool c; //carry
operator uint() const { return data & 0x8fd5 | 0x7002; }
auto& operator =(uint value) { return data = value, *this; }
auto& operator&=(uint value) { return data &= value, *this; }
auto& operator|=(uint value) { return data |= value, *this; }
auto& operator^=(uint value) { return data ^= value, *this; }
} f;
} r;
};

128
nall/bit-field.hpp Normal file
View File

@ -0,0 +1,128 @@
#pragma once
namespace nall {
template<typename type> struct BitFieldReference {
BitFieldReference(type& data, uint lo, uint hi)
: data(data), lo(lo), hi(hi), bits(hi + lo - 1), mask((~0ull >> (64 - bits)) << lo) {
}
inline explicit operator bool() const { return data & mask; }
inline operator type() const { return get(); }
inline auto& operator=(const BitFieldReference& value) { return set(value.data); }
template<typename T> inline auto& operator=(const T& value) { return set(value << lo); }
inline auto operator++(int) { type value = get(); set(data + (1 << lo)); return value; }
inline auto operator--(int) { type value = get(); set(data - (1 << lo)); return value; }
inline auto& operator++() { return set(data + (1 << lo)); }
inline auto& operator--() { return set(data - (1 << lo)); }
inline auto& operator &=(const type value) { return set(data & (value << lo)); }
inline auto& operator |=(const type value) { return set(data | (value << lo)); }
inline auto& operator ^=(const type value) { return set(data ^ (value << lo)); }
inline auto& operator<<=(const type value) { return set((data & mask) << value); }
inline auto& operator>>=(const type value) { return set((data & mask) >> value); }
inline auto& operator +=(const type value) { return set(data + (value << lo)); }
inline auto& operator -=(const type value) { return set(data - (value << lo)); }
inline auto& operator *=(const type value) { return set((get() * value) << lo); }
inline auto& operator /=(const type value) { return set((get() / value) << lo); }
inline auto& operator %=(const type value) { return set((get() % value) << lo); }
const uint lo;
const uint hi;
const uint bits;
const uint mask;
private:
type& data;
inline auto get() const -> type {
return (data & mask) >> lo;
}
inline auto set(type value) -> BitFieldReference& {
return data = (data & ~mask) | (value & mask), *this;
}
};
template<typename type, uint Lo, uint Hi = ~0> struct BitField {
enum : uint { lo = Lo <= Hi ? Lo : Hi };
enum : uint { hi = Hi >= Lo ? Hi : Lo };
enum : uint { bits = hi - lo + 1 };
enum : uint { mask = (~0ull >> (64 - bits)) << lo };
static_assert(hi < sizeof(type) * 8, "");
inline BitField() = default;
inline BitField(const BitField& value) { set(value.data); }
template<typename T> inline BitField(const T& value) { set(value << lo); }
inline explicit operator bool() const { return data & mask; }
inline operator type() const { return get(); }
inline operator BitFieldReference<type>() { return {data, lo, hi}; }
inline auto& operator=(const BitField& value) { return set(value.data); }
template<typename T> inline auto& operator=(const T& value) { return set(value << lo); }
inline auto operator++(int) { type value = get(); set(data + (1 << lo)); return value; }
inline auto operator--(int) { type value = get(); set(data - (1 << lo)); return value; }
inline auto& operator++() { return set(data + (1 << lo)); }
inline auto& operator--() { return set(data - (1 << lo)); }
inline auto& operator &=(const type value) { return set(data & (value << lo)); }
inline auto& operator |=(const type value) { return set(data | (value << lo)); }
inline auto& operator ^=(const type value) { return set(data ^ (value << lo)); }
inline auto& operator<<=(const type value) { return set((data & mask) << value); }
inline auto& operator>>=(const type value) { return set((data & mask) >> value); }
inline auto& operator +=(const type value) { return set(data + (value << lo)); }
inline auto& operator -=(const type value) { return set(data - (value << lo)); }
inline auto& operator *=(const type value) { return set((get() * value) << lo); }
inline auto& operator /=(const type value) { return set((get() / value) << lo); }
inline auto& operator %=(const type value) { return set((get() % value) << lo); }
private:
type data;
inline auto get() const -> type {
return (data & mask) >> lo;
}
inline auto set(type value) -> BitField& {
return data = (data & ~mask) | (value & mask), *this;
}
};
template<typename type, uint Bit> struct BitField<type, Bit, ~0> {
enum : uint { bit = Bit };
enum : uint { mask = 1ull << bit };
static_assert(bit < sizeof(type) * 8, "");
inline BitField() = default;
inline BitField(const BitField& value) { set(value.get()); }
template<typename T> inline BitField(const bool value) { set(value); }
inline operator bool() const { return get(); }
inline operator BitFieldReference<type>() { return {data, bit, bit}; }
inline auto& operator=(const BitField& value) { return set(value.get()); }
inline auto& operator=(const bool value) { return set(value); }
inline auto& operator&=(const bool value) { return set(get() & value); }
inline auto& operator|=(const bool value) { return set(get() | value); }
inline auto& operator^=(const bool value) { return set(get() ^ value); }
private:
type data;
inline auto get() const -> bool {
return data & mask;
}
inline auto set(bool value) -> BitField& {
return data = (data & ~mask) | (value << bit), *this;
}
};
}

View File

@ -17,7 +17,8 @@
#include <nall/any.hpp>
#include <nall/atoi.hpp>
#include <nall/bit.hpp>
#include <nall/bitvector.hpp>
#include <nall/bit-field.hpp>
#include <nall/bit-vector.hpp>
#include <nall/config.hpp>
#include <nall/directory.hpp>
#include <nall/dl.hpp>

View File

@ -5,52 +5,6 @@
namespace nall {
template<typename Type, uint Lo, uint Hi> struct BitField {
static_assert(Lo <= Hi, "");
static_assert(Hi < sizeof(Type) * 8, "");
inline BitField() = default;
inline BitField(const BitField& value) { set(value.data); }
template<typename T> inline BitField(const T& value) { set(value << Lo); }
//inline explicit operator bool() const { return data & Mask; }
inline operator Type() const { return get(); }
inline auto& operator=(const BitField& value) { return set(value.data); }
template<typename T> inline auto& operator=(const T& value) { return set(value << Lo); }
inline auto operator++(int) { Type value = get(); set(data + (1 << Lo)); return value; }
inline auto operator--(int) { Type value = get(); set(data - (1 << Lo)); return value; }
inline auto& operator++() { return set(data + (1 << Lo)); }
inline auto& operator--() { return set(data - (1 << Lo)); }
inline auto& operator &=(const Type value) { return set(data & (value << Lo)); }
inline auto& operator |=(const Type value) { return set(data | (value << Lo)); }
inline auto& operator ^=(const Type value) { return set(data ^ (value << Lo)); }
inline auto& operator<<=(const Type value) { return set(data << value); }
inline auto& operator>>=(const Type value) { return set(data >> value); }
inline auto& operator +=(const Type value) { return set(data + (value << Lo)); }
inline auto& operator -=(const Type value) { return set(data - (value << Lo)); }
inline auto& operator *=(const Type value) { return set((get() * value) << Lo); }
inline auto& operator /=(const Type value) { return set((get() / value) << Lo); }
inline auto& operator %=(const Type value) { return set((get() % value) << Lo); }
private:
enum : uint { Bits = Hi - Lo + 1 };
enum : uint { Mask = ((1ull << Bits) - 1) << Lo };
Type data;
inline auto get() const -> Type {
return (data & Mask) >> Lo;
}
inline auto set(Type value) -> BitField& {
data = (data & ~Mask) | (value & Mask);
return *this;
}
};
struct Boolean {
inline Boolean() : data(false) {}
template<typename T> inline Boolean(const T& value) : data(value) {}