mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
b08449215a
commit
50420e3dd2
|
@ -9,7 +9,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "higan";
|
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 Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "http://byuu.org/";
|
static const string Website = "http://byuu.org/";
|
||||||
|
|
|
@ -27,7 +27,7 @@ auto ARM::arm_opcode(uint32 rm) {
|
||||||
|
|
||||||
if(exceptionMode() && d == 15 && save) {
|
if(exceptionMode() && d == 15 && save) {
|
||||||
cpsr() = spsr();
|
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.f = rm & 0x00000040;
|
||||||
psr.t = rm & 0x00000020;
|
psr.t = rm & 0x00000020;
|
||||||
psr.m = rm & 0x0000001f;
|
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(s && (list & 0x8000)) {
|
||||||
if(mode() != Processor::Mode::USR && mode() != Processor::Mode::SYS) {
|
if(mode() != Processor::Mode::USR && mode() != Processor::Mode::SYS) {
|
||||||
cpsr() = spsr();
|
cpsr() = spsr();
|
||||||
processor.setMode((Processor::Mode)cpsr().m);
|
processor.setMode((Processor::Mode)(uint)cpsr().m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -19,33 +19,24 @@ struct GPR {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PSR {
|
struct PSR {
|
||||||
inline operator uint32_t() const {
|
union {
|
||||||
return (n << 31) + (z << 30) + (c << 29) + (v << 28)
|
uint32_t data = 0;
|
||||||
+ (i << 7) + (f << 6) + (t << 5) + (m << 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) {
|
PSR() = default;
|
||||||
n = d & (1 << 31);
|
PSR(const PSR& value) { data = value.data; }
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto serialize(serializer&) -> void;
|
inline operator uint() const { return data & 0xf00000ff; }
|
||||||
|
inline auto& operator=(uint value) { return data = value, *this; }
|
||||||
bool n = false; //negative
|
inline auto& operator=(const PSR& value) { return data = value.data, *this; }
|
||||||
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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Pipeline {
|
struct Pipeline {
|
||||||
|
@ -125,6 +116,6 @@ alwaysinline auto cpsr() -> PSR& { return processor.cpsr; }
|
||||||
alwaysinline auto spsr() -> PSR& { return *processor.spsr; }
|
alwaysinline auto spsr() -> PSR& { return *processor.spsr; }
|
||||||
alwaysinline auto carryout() -> bool& { return processor.carryout; }
|
alwaysinline auto carryout() -> bool& { return processor.carryout; }
|
||||||
alwaysinline auto instruction() -> uint32 { return pipeline.execute.instruction; }
|
alwaysinline auto instruction() -> uint32 { return pipeline.execute.instruction; }
|
||||||
alwaysinline auto mode() -> Processor::Mode { return (Processor::Mode)processor.cpsr.m; }
|
alwaysinline auto mode() -> Processor::Mode { return (Processor::Mode)(uint)processor.cpsr.m; }
|
||||||
alwaysinline auto privilegedMode() const -> bool { return (Processor::Mode)processor.cpsr.m != Processor::Mode::USR; }
|
alwaysinline auto privilegedMode() const -> bool { return (Processor::Mode)(uint)processor.cpsr.m != Processor::Mode::USR; }
|
||||||
alwaysinline auto exceptionMode() const -> bool { return privilegedMode() && (Processor::Mode)processor.cpsr.m != Processor::Mode::SYS; }
|
alwaysinline auto exceptionMode() const -> bool { return privilegedMode() && (Processor::Mode)(uint)processor.cpsr.m != Processor::Mode::SYS; }
|
||||||
|
|
|
@ -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 {
|
auto ARM::serialize(serializer& s) -> void {
|
||||||
s.integer(processor.r0.data);
|
s.integer(processor.r0.data);
|
||||||
s.integer(processor.r1.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.r12.data);
|
||||||
s.integer(processor.fiq.sp.data);
|
s.integer(processor.fiq.sp.data);
|
||||||
s.integer(processor.fiq.lr.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.sp.data);
|
||||||
s.integer(processor.irq.lr.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.sp.data);
|
||||||
s.integer(processor.svc.lr.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.sp.data);
|
||||||
s.integer(processor.abt.lr.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.sp.data);
|
||||||
s.integer(processor.und.lr.data);
|
s.integer(processor.und.lr.data);
|
||||||
processor.und.spsr.serialize(s);
|
s.integer(processor.und.spsr.data);
|
||||||
|
|
||||||
s.integer(processor.pc.data);
|
s.integer(processor.pc.data);
|
||||||
processor.cpsr.serialize(s);
|
s.integer(processor.cpsr.data);
|
||||||
s.integer(processor.carryout);
|
s.integer(processor.carryout);
|
||||||
s.integer(processor.irqline);
|
s.integer(processor.irqline);
|
||||||
|
|
||||||
|
@ -68,5 +57,5 @@ auto ARM::serialize(serializer& s) -> void {
|
||||||
|
|
||||||
s.integer(crash);
|
s.integer(crash);
|
||||||
|
|
||||||
processor.setMode((Processor::Mode)cpsr().m);
|
processor.setMode((Processor::Mode)(uint)cpsr().m);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,39 +34,25 @@ struct Register {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SFR {
|
struct SFR {
|
||||||
bool irq; //interrupt flag
|
union {
|
||||||
bool b; //WITH flag
|
uint16_t data = 0;
|
||||||
bool ih; //immediate higher 8-bit flag
|
BitField<uint16_t, 15> irq; //interrupt flag
|
||||||
bool il; //immediate lower 8-bit flag
|
BitField<uint16_t, 12> b; //with flag
|
||||||
bool alt2; //ALT2 mode
|
BitField<uint16_t, 11> ih; //immediate higher 8-bit flag
|
||||||
bool alt1; //ALT2 instruction mode
|
BitField<uint16_t, 10> il; //immediate lower 8-bit flag
|
||||||
bool r; //ROM r14 read flag
|
BitField<uint16_t, 9> alt2; //alt2 instruction mode
|
||||||
bool g; //GO flag
|
BitField<uint16_t, 8> alt1; //alt1 instruction mode
|
||||||
bool ov; //overflow flag
|
BitField<uint16_t, 6> r; //ROM r14 read flag
|
||||||
bool s; //sign flag
|
BitField<uint16_t, 5> g; //go flag
|
||||||
bool cy; //carry flag
|
BitField<uint16_t, 4> ov; //overflow flag
|
||||||
bool z; //zero 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 {
|
inline operator uint() const { return data & 0x9f7e; }
|
||||||
return (irq << 15) | (b << 12) | (ih << 11) | (il << 10) | (alt2 << 9) | (alt1 << 8)
|
inline auto& operator=(const uint value) { return data = value, *this; }
|
||||||
| (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;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SCMR {
|
struct SCMR {
|
||||||
|
|
|
@ -7,19 +7,7 @@ auto GSU::serialize(serializer& s) -> void {
|
||||||
s.integer(regs.r[n].modified);
|
s.integer(regs.r[n].modified);
|
||||||
}
|
}
|
||||||
|
|
||||||
s.integer(regs.sfr.irq);
|
s.integer(regs.sfr.data);
|
||||||
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.pbr);
|
s.integer(regs.pbr);
|
||||||
s.integer(regs.rombr);
|
s.integer(regs.rombr);
|
||||||
s.integer(regs.rambr);
|
s.integer(regs.rambr);
|
||||||
|
|
|
@ -165,9 +165,9 @@ L op_readpc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto R6502::opi_clear_flag(bool& flag) {
|
auto R6502::opi_clear_flag(uint bit) {
|
||||||
L op_readpc();
|
L op_readpc();
|
||||||
flag = 0;
|
regs.p &= ~(1 << bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto R6502::opi_decrement(uint8& r) {
|
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);
|
L op_writezp(zp + regs.x, rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto R6502::opi_set_flag(bool& flag) {
|
auto R6502::opi_set_flag(uint bit) {
|
||||||
L op_readpc();
|
L op_readpc();
|
||||||
flag = 1;
|
regs.p |= 1 << bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto R6502::opi_shift(fp op) {
|
auto R6502::opi_shift(fp op) {
|
||||||
|
|
|
@ -64,7 +64,7 @@ I case 0x0c: return opill_nop_absolute();
|
||||||
I case 0x14: return opill_nop_zero_page_x();
|
I case 0x14: return opill_nop_zero_page_x();
|
||||||
case 0x15: return opi_read_zero_page_x(&R6502::opf_ora);
|
case 0x15: return opi_read_zero_page_x(&R6502::opf_ora);
|
||||||
case 0x16: return opi_rmw_zero_page_x(&R6502::opf_asl);
|
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);
|
case 0x19: return opi_read_absolute_y(&R6502::opf_ora);
|
||||||
I case 0x1a: return opill_nop_implied();
|
I case 0x1a: return opill_nop_implied();
|
||||||
I case 0x1c: return opill_nop_absolute_x();
|
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();
|
I case 0x34: return opill_nop_zero_page_x();
|
||||||
case 0x35: return opi_read_zero_page_x(&R6502::opf_and);
|
case 0x35: return opi_read_zero_page_x(&R6502::opf_and);
|
||||||
case 0x36: return opi_rmw_zero_page_x(&R6502::opf_rol);
|
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);
|
case 0x39: return opi_read_absolute_y(&R6502::opf_and);
|
||||||
I case 0x3a: return opill_nop_implied();
|
I case 0x3a: return opill_nop_implied();
|
||||||
I case 0x3c: return opill_nop_absolute_x();
|
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();
|
I case 0x54: return opill_nop_zero_page_x();
|
||||||
case 0x55: return opi_read_zero_page_x(&R6502::opf_eor);
|
case 0x55: return opi_read_zero_page_x(&R6502::opf_eor);
|
||||||
case 0x56: return opi_rmw_zero_page_x(&R6502::opf_lsr);
|
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);
|
case 0x59: return opi_read_absolute_y(&R6502::opf_eor);
|
||||||
I case 0x5a: return opill_nop_implied();
|
I case 0x5a: return opill_nop_implied();
|
||||||
I case 0x5c: return opill_nop_absolute_x();
|
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 0x71: return opi_read_indirect_zero_page_y(&R6502::opf_adc);
|
||||||
case 0x75: return opi_read_zero_page_x(&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 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);
|
case 0x79: return opi_read_absolute_y(&R6502::opf_adc);
|
||||||
I case 0x7a: return opill_nop_implied();
|
I case 0x7a: return opill_nop_implied();
|
||||||
I case 0x7c: return opill_nop_absolute_x();
|
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 0xb4: return opi_read_zero_page_x(&R6502::opf_ldy);
|
||||||
case 0xb5: return opi_read_zero_page_x(&R6502::opf_lda);
|
case 0xb5: return opi_read_zero_page_x(&R6502::opf_lda);
|
||||||
case 0xb6: return opi_read_zero_page_y(&R6502::opf_ldx);
|
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 0xb9: return opi_read_absolute_y(&R6502::opf_lda);
|
||||||
case 0xba: return opi_transfer(regs.s, regs.x, 1);
|
case 0xba: return opi_transfer(regs.s, regs.x, 1);
|
||||||
case 0xbc: return opi_read_absolute_x(&R6502::opf_ldy);
|
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();
|
I case 0xd4: return opill_nop_zero_page_x();
|
||||||
case 0xd5: return opi_read_zero_page_x(&R6502::opf_cmp);
|
case 0xd5: return opi_read_zero_page_x(&R6502::opf_cmp);
|
||||||
case 0xd6: return opi_rmw_zero_page_x(&R6502::opf_dec);
|
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);
|
case 0xd9: return opi_read_absolute_y(&R6502::opf_cmp);
|
||||||
I case 0xda: return opill_nop_implied();
|
I case 0xda: return opill_nop_implied();
|
||||||
I case 0xdc: return opill_nop_absolute_x();
|
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();
|
I case 0xf4: return opill_nop_zero_page_x();
|
||||||
case 0xf5: return opi_read_zero_page_x(&R6502::opf_sbc);
|
case 0xf5: return opi_read_zero_page_x(&R6502::opf_sbc);
|
||||||
case 0xf6: return opi_rmw_zero_page_x(&R6502::opf_inc);
|
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);
|
case 0xf9: return opi_read_absolute_y(&R6502::opf_sbc);
|
||||||
I case 0xfa: return opill_nop_implied();
|
I case 0xfa: return opill_nop_implied();
|
||||||
I case 0xfc: return opill_nop_absolute_x();
|
I case 0xfc: return opill_nop_absolute_x();
|
||||||
|
|
|
@ -60,7 +60,7 @@ struct R6502 {
|
||||||
using fp = auto (R6502::*)() -> void;
|
using fp = auto (R6502::*)() -> void;
|
||||||
|
|
||||||
auto opi_branch(bool condition);
|
auto opi_branch(bool condition);
|
||||||
auto opi_clear_flag(bool& flag);
|
auto opi_clear_flag(uint bit);
|
||||||
auto opi_decrement(uint8& r);
|
auto opi_decrement(uint8& r);
|
||||||
auto opi_increment(uint8& r);
|
auto opi_increment(uint8& r);
|
||||||
auto opi_pull(uint8& r);
|
auto opi_pull(uint8& r);
|
||||||
|
@ -78,7 +78,7 @@ struct R6502 {
|
||||||
auto opi_rmw_absolute_x(fp);
|
auto opi_rmw_absolute_x(fp);
|
||||||
auto opi_rmw_zero_page(fp);
|
auto opi_rmw_zero_page(fp);
|
||||||
auto opi_rmw_zero_page_x(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_shift(fp);
|
||||||
auto opi_store_absolute(uint8& r);
|
auto opi_store_absolute(uint8& r);
|
||||||
auto opi_store_absolute_x(uint8& r);
|
auto opi_store_absolute_x(uint8& r);
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
struct Flags {
|
struct Flags {
|
||||||
inline operator uint() {
|
union {
|
||||||
return (n << 7) | (v << 6) | (d << 3) | (i << 2) | (z << 1) | (c << 0);
|
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& {
|
inline operator uint() { return data; }
|
||||||
n = data & 0x80; v = data & 0x40;
|
inline auto& operator =(uint value) { return data = value, *this; }
|
||||||
d = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01;
|
inline auto& operator&=(uint value) { return data &= value, *this; }
|
||||||
return *this;
|
inline auto& operator|=(uint value) { return data |= value, *this; }
|
||||||
}
|
inline auto& operator^=(uint value) { return data ^= value, *this; }
|
||||||
|
|
||||||
bool n, v, d, i, z, c;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Registers {
|
struct Registers {
|
||||||
|
@ -22,7 +26,8 @@ struct Registers {
|
||||||
struct Register16 {
|
struct Register16 {
|
||||||
union {
|
union {
|
||||||
uint16_t w;
|
uint16_t w;
|
||||||
struct { uint8_t order_lsb2(l, h); };
|
BitField<uint16_t, 0, 7> l;
|
||||||
|
BitField<uint16_t, 8, 15> h;
|
||||||
};
|
};
|
||||||
} abs, iabs;
|
} abs, iabs;
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,7 @@ auto R6502::serialize(serializer& s) -> void {
|
||||||
s.integer(regs.x);
|
s.integer(regs.x);
|
||||||
s.integer(regs.y);
|
s.integer(regs.y);
|
||||||
s.integer(regs.s);
|
s.integer(regs.s);
|
||||||
s.integer(regs.p.n);
|
s.integer(regs.p.data);
|
||||||
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(abs.w);
|
s.integer(abs.w);
|
||||||
s.integer(iabs.w);
|
s.integer(iabs.w);
|
||||||
|
|
|
@ -109,7 +109,7 @@ auto R65816::disassemble() -> string {
|
||||||
auto R65816::disassemble(uint24 addr, bool e, bool m, bool x) -> string {
|
auto R65816::disassemble(uint24 addr, bool e, bool m, bool x) -> string {
|
||||||
string s;
|
string s;
|
||||||
|
|
||||||
reg24 pc;
|
Reg24 pc;
|
||||||
pc.d = addr;
|
pc.d = addr;
|
||||||
s = {hex(pc, 6), " "};
|
s = {hex(pc, 6), " "};
|
||||||
|
|
||||||
|
|
|
@ -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();
|
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) {
|
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();
|
L ioIRQ();
|
||||||
to.l = from.l;
|
to.l = from.l;
|
||||||
r.p.n = (to.l & 0x80);
|
r.p.n = (to.l & 0x80);
|
||||||
r.p.z = (to.l == 0);
|
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();
|
L ioIRQ();
|
||||||
to.w = from.w;
|
to.w = from.w;
|
||||||
r.p.n = (to.w & 0x8000);
|
r.p.n = (to.w & 0x8000);
|
||||||
|
@ -139,12 +149,12 @@ E r.s.l = r.x.l;
|
||||||
N r.s.w = r.x.w;
|
N r.s.w = r.x.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto R65816::op_push_b(reg16& reg) {
|
auto R65816::op_push_b(Reg16& reg) {
|
||||||
io();
|
io();
|
||||||
L writeSP(reg.l);
|
L writeSP(reg.l);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto R65816::op_push_w(reg16& reg) {
|
auto R65816::op_push_w(Reg16& reg) {
|
||||||
io();
|
io();
|
||||||
writeSP(reg.h);
|
writeSP(reg.h);
|
||||||
L writeSP(reg.l);
|
L writeSP(reg.l);
|
||||||
|
@ -172,7 +182,7 @@ auto R65816::op_php() {
|
||||||
L writeSP(r.p);
|
L writeSP(r.p);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto R65816::op_pull_b(reg16& reg) {
|
auto R65816::op_pull_b(Reg16& reg) {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
L reg.l = readSP();
|
L reg.l = readSP();
|
||||||
|
@ -180,7 +190,7 @@ L reg.l = readSP();
|
||||||
r.p.z = (reg.l == 0);
|
r.p.z = (reg.l == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto R65816::op_pull_w(reg16& reg) {
|
auto R65816::op_pull_w(Reg16& reg) {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
reg.l = readSP();
|
reg.l = readSP();
|
||||||
|
|
|
@ -118,7 +118,7 @@ L rd.h = readDP(dp + 1);
|
||||||
call(op);
|
call(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto R65816::op_read_dpr_b(fp op, reg16& reg) {
|
auto R65816::op_read_dpr_b(fp op, Reg16& reg) {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
io2();
|
io2();
|
||||||
io();
|
io();
|
||||||
|
@ -126,7 +126,7 @@ L rd.l = readDP(dp + reg.w);
|
||||||
call(op);
|
call(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto R65816::op_read_dpr_w(fp op, reg16& reg) {
|
auto R65816::op_read_dpr_w(fp op, Reg16& reg) {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
io2();
|
io2();
|
||||||
io();
|
io();
|
||||||
|
|
|
@ -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();
|
L ioIRQ();
|
||||||
reg.l += adjust;
|
reg.l += adjust;
|
||||||
r.p.n = (reg.l & 0x80);
|
r.p.n = (reg.l & 0x80);
|
||||||
r.p.z = (reg.l == 0);
|
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();
|
L ioIRQ();
|
||||||
reg.w += adjust;
|
reg.w += adjust;
|
||||||
r.p.n = (reg.w & 0x8000);
|
r.p.n = (reg.w & 0x8000);
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
auto R65816::op_write_addr_b(reg16& reg) {
|
auto R65816::op_write_addr_b(Reg16& reg) {
|
||||||
aa.l = readPC();
|
aa.l = readPC();
|
||||||
aa.h = readPC();
|
aa.h = readPC();
|
||||||
L writeDB(aa.w, reg);
|
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.l = readPC();
|
||||||
aa.h = readPC();
|
aa.h = readPC();
|
||||||
writeDB(aa.w + 0, reg >> 0);
|
writeDB(aa.w + 0, reg >> 0);
|
||||||
L writeDB(aa.w + 1, reg >> 8);
|
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.l = readPC();
|
||||||
aa.h = readPC();
|
aa.h = readPC();
|
||||||
io();
|
io();
|
||||||
L writeDB(aa.w + idx, reg);
|
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.l = readPC();
|
||||||
aa.h = readPC();
|
aa.h = readPC();
|
||||||
io();
|
io();
|
||||||
|
@ -26,14 +26,14 @@ auto R65816::op_write_addrr_w(reg16& reg, reg16& idx) {
|
||||||
L writeDB(aa.w + idx + 1, reg >> 8);
|
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.l = readPC();
|
||||||
aa.h = readPC();
|
aa.h = readPC();
|
||||||
aa.b = readPC();
|
aa.b = readPC();
|
||||||
L writeLong(aa.d + idx, r.a.l);
|
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.l = readPC();
|
||||||
aa.h = readPC();
|
aa.h = readPC();
|
||||||
aa.b = 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);
|
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();
|
dp = readPC();
|
||||||
io2();
|
io2();
|
||||||
L writeDP(dp, reg);
|
L writeDP(dp, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto R65816::op_write_dp_w(reg16& reg) {
|
auto R65816::op_write_dp_w(Reg16& reg) {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
io2();
|
io2();
|
||||||
writeDP(dp + 0, reg >> 0);
|
writeDP(dp + 0, reg >> 0);
|
||||||
L writeDP(dp + 1, reg >> 8);
|
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();
|
dp = readPC();
|
||||||
io2();
|
io2();
|
||||||
io();
|
io();
|
||||||
L writeDP(dp + idx, reg);
|
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();
|
dp = readPC();
|
||||||
io2();
|
io2();
|
||||||
io();
|
io();
|
||||||
|
|
|
@ -88,8 +88,8 @@ struct R65816 {
|
||||||
auto op_read_longx_w(fp);
|
auto op_read_longx_w(fp);
|
||||||
auto op_read_dp_b(fp);
|
auto op_read_dp_b(fp);
|
||||||
auto op_read_dp_w(fp);
|
auto op_read_dp_w(fp);
|
||||||
auto op_read_dpr_b(fp, reg16&);
|
auto op_read_dpr_b(fp, Reg16&);
|
||||||
auto op_read_dpr_w(fp, reg16&);
|
auto op_read_dpr_w(fp, Reg16&);
|
||||||
auto op_read_idp_b(fp);
|
auto op_read_idp_b(fp);
|
||||||
auto op_read_idp_w(fp);
|
auto op_read_idp_w(fp);
|
||||||
auto op_read_idpx_b(fp);
|
auto op_read_idpx_b(fp);
|
||||||
|
@ -106,16 +106,16 @@ struct R65816 {
|
||||||
auto op_read_isry_w(fp);
|
auto op_read_isry_w(fp);
|
||||||
|
|
||||||
//opcode_write.cpp
|
//opcode_write.cpp
|
||||||
auto op_write_addr_b(reg16&);
|
auto op_write_addr_b(Reg16&);
|
||||||
auto op_write_addr_w(reg16&);
|
auto op_write_addr_w(Reg16&);
|
||||||
auto op_write_addrr_b(reg16&, reg16&);
|
auto op_write_addrr_b(Reg16&, Reg16&);
|
||||||
auto op_write_addrr_w(reg16&, reg16&);
|
auto op_write_addrr_w(Reg16&, Reg16&);
|
||||||
auto op_write_longr_b(reg16&);
|
auto op_write_longr_b(Reg16&);
|
||||||
auto op_write_longr_w(reg16&);
|
auto op_write_longr_w(Reg16&);
|
||||||
auto op_write_dp_b(reg16&);
|
auto op_write_dp_b(Reg16&);
|
||||||
auto op_write_dp_w(reg16&);
|
auto op_write_dp_w(Reg16&);
|
||||||
auto op_write_dpr_b(reg16&, reg16&);
|
auto op_write_dpr_b(Reg16&, Reg16&);
|
||||||
auto op_write_dpr_w(reg16&, reg16&);
|
auto op_write_dpr_w(Reg16&, Reg16&);
|
||||||
auto op_sta_idp_b();
|
auto op_sta_idp_b();
|
||||||
auto op_sta_idp_w();
|
auto op_sta_idp_w();
|
||||||
auto op_sta_ildp_b();
|
auto op_sta_ildp_b();
|
||||||
|
@ -132,8 +132,8 @@ struct R65816 {
|
||||||
auto op_sta_isry_w();
|
auto op_sta_isry_w();
|
||||||
|
|
||||||
//opcode_rmw.cpp
|
//opcode_rmw.cpp
|
||||||
auto op_adjust_imm_b(reg16&, int);
|
auto op_adjust_imm_b(Reg16&, int);
|
||||||
auto op_adjust_imm_w(reg16&, int);
|
auto op_adjust_imm_w(Reg16&, int);
|
||||||
auto op_asl_imm_b();
|
auto op_asl_imm_b();
|
||||||
auto op_asl_imm_w();
|
auto op_asl_imm_w();
|
||||||
auto op_lsr_imm_b();
|
auto op_lsr_imm_b();
|
||||||
|
@ -177,22 +177,23 @@ struct R65816 {
|
||||||
auto op_stp();
|
auto op_stp();
|
||||||
auto op_wai();
|
auto op_wai();
|
||||||
auto op_xce();
|
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_pflag(bool);
|
||||||
auto op_transfer_b(reg16&, reg16&);
|
auto op_transfer_b(Reg16&, Reg16&);
|
||||||
auto op_transfer_w(reg16&, reg16&);
|
auto op_transfer_w(Reg16&, Reg16&);
|
||||||
auto op_tcs();
|
auto op_tcs();
|
||||||
auto op_tsx_b();
|
auto op_tsx_b();
|
||||||
auto op_tsx_w();
|
auto op_tsx_w();
|
||||||
auto op_txs();
|
auto op_txs();
|
||||||
auto op_push_b(reg16&);
|
auto op_push_b(Reg16&);
|
||||||
auto op_push_w(reg16&);
|
auto op_push_w(Reg16&);
|
||||||
auto op_phd();
|
auto op_phd();
|
||||||
auto op_phb();
|
auto op_phb();
|
||||||
auto op_phk();
|
auto op_phk();
|
||||||
auto op_php();
|
auto op_php();
|
||||||
auto op_pull_b(reg16&);
|
auto op_pull_b(Reg16&);
|
||||||
auto op_pull_w(reg16&);
|
auto op_pull_w(Reg16&);
|
||||||
auto op_pld();
|
auto op_pld();
|
||||||
auto op_plb();
|
auto op_plb();
|
||||||
auto op_plp();
|
auto op_plp();
|
||||||
|
@ -207,7 +208,7 @@ struct R65816 {
|
||||||
auto serialize(serializer&) -> void;
|
auto serialize(serializer&) -> void;
|
||||||
|
|
||||||
Registers r;
|
Registers r;
|
||||||
reg24 aa, rd;
|
Reg24 aa, rd;
|
||||||
uint8 sp, dp;
|
uint8 sp, dp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,88 +1,80 @@
|
||||||
struct Flags {
|
struct Flags {
|
||||||
bool n{0};
|
union {
|
||||||
bool v{0};
|
uint8_t b = 0;
|
||||||
bool m{0};
|
BitField<uint8_t, 7> n;
|
||||||
bool x{0};
|
BitField<uint8_t, 6> v;
|
||||||
bool d{0};
|
BitField<uint8_t, 5> m;
|
||||||
bool i{0};
|
BitField<uint8_t, 4> x;
|
||||||
bool z{0};
|
BitField<uint8_t, 3> d;
|
||||||
bool c{0};
|
BitField<uint8_t, 2> i;
|
||||||
|
BitField<uint8_t, 1> z;
|
||||||
inline operator uint() const {
|
BitField<uint8_t, 0> c;
|
||||||
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;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct reg16 {
|
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 {
|
||||||
union {
|
union {
|
||||||
uint16_t w = 0;
|
uint16_t w = 0;
|
||||||
//BitField<uint16_t, 0, 7> l;
|
BitField<uint16_t, 0, 7> l;
|
||||||
//BitField<uint16_t, 8, 15> h;
|
BitField<uint16_t, 8, 15> h;
|
||||||
struct { uint8_t order_lsb2(l, h); };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline operator uint() const { return w; }
|
inline operator uint() const { return w; }
|
||||||
inline auto operator =(uint i) -> uint { return w = i; }
|
inline auto operator =(uint value) -> uint { return w = value; }
|
||||||
inline auto operator |=(uint i) -> uint { return w |= i; }
|
inline auto operator |=(uint value) -> uint { return w |= value; }
|
||||||
inline auto operator ^=(uint i) -> uint { return w ^= i; }
|
inline auto operator ^=(uint value) -> uint { return w ^= value; }
|
||||||
inline auto operator &=(uint i) -> uint { return w &= i; }
|
inline auto operator &=(uint value) -> uint { return w &= value; }
|
||||||
inline auto operator<<=(uint i) -> uint { return w <<= i; }
|
inline auto operator<<=(uint value) -> uint { return w <<= value; }
|
||||||
inline auto operator>>=(uint i) -> uint { return w >>= i; }
|
inline auto operator>>=(uint value) -> uint { return w >>= value; }
|
||||||
inline auto operator +=(uint i) -> uint { return w += i; }
|
inline auto operator +=(uint value) -> uint { return w += value; }
|
||||||
inline auto operator -=(uint i) -> uint { return w -= i; }
|
inline auto operator -=(uint value) -> uint { return w -= value; }
|
||||||
inline auto operator *=(uint i) -> uint { return w *= i; }
|
inline auto operator *=(uint value) -> uint { return w *= value; }
|
||||||
inline auto operator /=(uint i) -> uint { return w /= i; }
|
inline auto operator /=(uint value) -> uint { return w /= value; }
|
||||||
inline auto operator %=(uint i) -> uint { return w %= i; }
|
inline auto operator %=(uint value) -> uint { return w %= value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct reg24 {
|
struct Reg24 {
|
||||||
union {
|
union {
|
||||||
uint32_t d = 0;
|
uint32_t d = 0;
|
||||||
//BitField<uint32_t, 0, 15> w;
|
BitField<uint32_t, 0, 7> l;
|
||||||
//BitField<uint32_t, 16, 31> wh;
|
BitField<uint32_t, 8, 15> h;
|
||||||
//BitField<uint32_t, 0, 7> l;
|
BitField<uint32_t, 16, 23> b;
|
||||||
//BitField<uint32_t, 8, 15> h;
|
BitField<uint32_t, 0, 15> w;
|
||||||
//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); };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline operator uint() const { return d; }
|
inline operator uint() const { return d; }
|
||||||
inline auto operator =(uint i) -> uint { return d = uclip<24>(i); }
|
inline auto operator =(uint value) -> uint { return d = uint24( value); }
|
||||||
inline auto operator |=(uint i) -> uint { return d = uclip<24>(d | i); }
|
inline auto operator |=(uint value) -> uint { return d = uint24(d | value); }
|
||||||
inline auto operator ^=(uint i) -> uint { return d = uclip<24>(d ^ i); }
|
inline auto operator ^=(uint value) -> uint { return d = uint24(d ^ value); }
|
||||||
inline auto operator &=(uint i) -> uint { return d = uclip<24>(d & i); }
|
inline auto operator &=(uint value) -> uint { return d = uint24(d & value); }
|
||||||
inline auto operator<<=(uint i) -> uint { return d = uclip<24>(d << i); }
|
inline auto operator<<=(uint value) -> uint { return d = uint24(d << value); }
|
||||||
inline auto operator>>=(uint i) -> uint { return d = uclip<24>(d >> i); }
|
inline auto operator>>=(uint value) -> uint { return d = uint24(d >> value); }
|
||||||
inline auto operator +=(uint i) -> uint { return d = uclip<24>(d + i); }
|
inline auto operator +=(uint value) -> uint { return d = uint24(d + value); }
|
||||||
inline auto operator -=(uint i) -> uint { return d = uclip<24>(d - i); }
|
inline auto operator -=(uint value) -> uint { return d = uint24(d - value); }
|
||||||
inline auto operator *=(uint i) -> uint { return d = uclip<24>(d * i); }
|
inline auto operator *=(uint value) -> uint { return d = uint24(d * value); }
|
||||||
inline auto operator /=(uint i) -> uint { return d = uclip<24>(d / i); }
|
inline auto operator /=(uint value) -> uint { return d = uint24(d / value); }
|
||||||
inline auto operator %=(uint i) -> uint { return d = uclip<24>(d % i); }
|
inline auto operator %=(uint value) -> uint { return d = uint24(d % value); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Registers {
|
struct Registers {
|
||||||
reg24 pc;
|
Reg24 pc;
|
||||||
reg16 a;
|
Reg16 a;
|
||||||
reg16 x;
|
Reg16 x;
|
||||||
reg16 y;
|
Reg16 y;
|
||||||
reg16 z; //pseudo-register (zero register)
|
Reg16 z; //pseudo-register (zero register)
|
||||||
reg16 s;
|
Reg16 s;
|
||||||
reg16 d;
|
Reg16 d;
|
||||||
Flags p;
|
Flags p;
|
||||||
uint8 db{0};
|
uint8 db = 0;
|
||||||
bool e{0};
|
bool e = false;
|
||||||
|
|
||||||
bool irq{0}; //IRQ pin (0 = low, 1 = trigger)
|
bool irq = false; //IRQ pin (0 = low, 1 = trigger)
|
||||||
bool wai{0}; //raised during wai, cleared after interrupt triggered
|
bool wai = false; //raised during wai, cleared after interrupt triggered
|
||||||
uint8 mdr{0}; //memory data register
|
uint8 mdr = 0; //memory data register
|
||||||
uint16 vector{0}; //interrupt vector address
|
uint16 vector = 0; //interrupt vector address
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,14 +8,7 @@ auto R65816::serialize(serializer& s) -> void {
|
||||||
s.integer(r.s.w);
|
s.integer(r.s.w);
|
||||||
s.integer(r.d.w);
|
s.integer(r.d.w);
|
||||||
|
|
||||||
s.integer(r.p.n);
|
s.integer(r.p.b);
|
||||||
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.db);
|
s.integer(r.db);
|
||||||
s.integer(r.e);
|
s.integer(r.e);
|
||||||
|
|
|
@ -38,7 +38,7 @@ auto R65816::instruction() -> void {
|
||||||
opMFI(0x15, read_dpr, ora, r.x)
|
opMFI(0x15, read_dpr, ora, r.x)
|
||||||
opMF (0x16, adjust_dpx, asl)
|
opMF (0x16, adjust_dpx, asl)
|
||||||
opMF (0x17, read_ildpy, ora)
|
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)
|
opMF (0x19, read_addry, ora)
|
||||||
opMII(0x1a, adjust_imm, r.a, +1)
|
opMII(0x1a, adjust_imm, r.a, +1)
|
||||||
opA (0x1b, tcs)
|
opA (0x1b, tcs)
|
||||||
|
@ -70,7 +70,7 @@ auto R65816::instruction() -> void {
|
||||||
opMFI(0x35, read_dpr, and, r.x)
|
opMFI(0x35, read_dpr, and, r.x)
|
||||||
opMF (0x36, adjust_dpx, rol)
|
opMF (0x36, adjust_dpx, rol)
|
||||||
opMF (0x37, read_ildpy, and)
|
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)
|
opMF (0x39, read_addry, and)
|
||||||
opMII(0x3a, adjust_imm, r.a, -1)
|
opMII(0x3a, adjust_imm, r.a, -1)
|
||||||
opAII(0x3b, transfer_w, r.s, r.a)
|
opAII(0x3b, transfer_w, r.s, r.a)
|
||||||
|
@ -102,7 +102,7 @@ auto R65816::instruction() -> void {
|
||||||
opMFI(0x55, read_dpr, eor, r.x)
|
opMFI(0x55, read_dpr, eor, r.x)
|
||||||
opMF (0x56, adjust_dpx, lsr)
|
opMF (0x56, adjust_dpx, lsr)
|
||||||
opMF (0x57, read_ildpy, eor)
|
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)
|
opMF (0x59, read_addry, eor)
|
||||||
opXI (0x5a, push, r.y)
|
opXI (0x5a, push, r.y)
|
||||||
opAII(0x5b, transfer_w, r.a, r.d)
|
opAII(0x5b, transfer_w, r.a, r.d)
|
||||||
|
@ -134,7 +134,7 @@ auto R65816::instruction() -> void {
|
||||||
opMFI(0x75, read_dpr, adc, r.x)
|
opMFI(0x75, read_dpr, adc, r.x)
|
||||||
opMF (0x76, adjust_dpx, ror)
|
opMF (0x76, adjust_dpx, ror)
|
||||||
opMF (0x77, read_ildpy, adc)
|
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)
|
opMF (0x79, read_addry, adc)
|
||||||
opXI (0x7a, pull, r.y)
|
opXI (0x7a, pull, r.y)
|
||||||
opAII(0x7b, transfer_w, r.d, r.a)
|
opAII(0x7b, transfer_w, r.d, r.a)
|
||||||
|
@ -198,7 +198,7 @@ auto R65816::instruction() -> void {
|
||||||
opMFI(0xb5, read_dpr, lda, r.x)
|
opMFI(0xb5, read_dpr, lda, r.x)
|
||||||
opXFI(0xb6, read_dpr, ldx, r.y)
|
opXFI(0xb6, read_dpr, ldx, r.y)
|
||||||
opMF (0xb7, read_ildpy, lda)
|
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)
|
opMF (0xb9, read_addry, lda)
|
||||||
opX (0xba, tsx)
|
opX (0xba, tsx)
|
||||||
opXII(0xbb, transfer, r.y, r.x)
|
opXII(0xbb, transfer, r.y, r.x)
|
||||||
|
@ -230,7 +230,7 @@ auto R65816::instruction() -> void {
|
||||||
opMFI(0xd5, read_dpr, cmp, r.x)
|
opMFI(0xd5, read_dpr, cmp, r.x)
|
||||||
opMF (0xd6, adjust_dpx, dec)
|
opMF (0xd6, adjust_dpx, dec)
|
||||||
opMF (0xd7, read_ildpy, cmp)
|
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)
|
opMF (0xd9, read_addry, cmp)
|
||||||
opXI (0xda, push, r.x)
|
opXI (0xda, push, r.x)
|
||||||
opA (0xdb, stp)
|
opA (0xdb, stp)
|
||||||
|
@ -262,7 +262,7 @@ auto R65816::instruction() -> void {
|
||||||
opMFI(0xf5, read_dpr, sbc, r.x)
|
opMFI(0xf5, read_dpr, sbc, r.x)
|
||||||
opMF (0xf6, adjust_dpx, inc)
|
opMF (0xf6, adjust_dpx, inc)
|
||||||
opMF (0xf7, read_ildpy, sbc)
|
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)
|
opMF (0xf9, read_addry, sbc)
|
||||||
opXI (0xfa, pull, r.x)
|
opXI (0xfa, pull, r.x)
|
||||||
opA (0xfb, xce)
|
opA (0xfb, xce)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#define call (this->*op)
|
#define call (this->*op)
|
||||||
|
|
||||||
auto SPC700::op_adjust(fps op, uint8_t& r) {
|
auto SPC700::op_adjust(fps op, reg r) {
|
||||||
io();
|
io();
|
||||||
r = call(r);
|
r = call(r);
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ auto SPC700::op_branch_bit() {
|
||||||
regs.pc += (int8)rd;
|
regs.pc += (int8)rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_pull(uint8_t& r) {
|
auto SPC700::op_pull(reg r) {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
r = readSP();
|
r = readSP();
|
||||||
|
@ -69,14 +69,14 @@ auto SPC700::op_push(uint8 r) {
|
||||||
writeSP(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.l = readPC();
|
||||||
dp.h = readPC();
|
dp.h = readPC();
|
||||||
rd = read(dp);
|
rd = read(dp);
|
||||||
r = call(r, rd);
|
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.l = readPC();
|
||||||
dp.h = readPC();
|
dp.h = readPC();
|
||||||
io();
|
io();
|
||||||
|
@ -84,18 +84,18 @@ auto SPC700::op_read_addri(fpb op, uint8_t& r) {
|
||||||
regs.a = call(regs.a, rd);
|
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();
|
rd = readPC();
|
||||||
r = call(r, rd);
|
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();
|
dp = readPC();
|
||||||
rd = readDP(dp);
|
rd = readDP(dp);
|
||||||
r = call(r, rd);
|
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();
|
dp = readPC();
|
||||||
io();
|
io();
|
||||||
rd = readDP(dp + i);
|
rd = readDP(dp + i);
|
||||||
|
@ -175,10 +175,10 @@ auto SPC700::op_set_bit() {
|
||||||
writeDP(dp, rd | (!(opcode & 0x10) << (opcode >> 5)));
|
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();
|
io();
|
||||||
if(&flag == ®s.p.i) io();
|
if(bit == regs.p.i.bit) io();
|
||||||
flag = data;
|
regs.p = value ? (regs.p | (1 << bit)) : (regs.p & ~(1 << bit));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_test_addr(bool set) {
|
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);
|
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();
|
io();
|
||||||
to = from;
|
to = from;
|
||||||
if(&to == ®s.s) return;
|
if(&to == ®s.s) return;
|
||||||
|
@ -199,14 +199,14 @@ auto SPC700::op_transfer(uint8_t& from, uint8_t& to) {
|
||||||
regs.p.z = (to == 0);
|
regs.p.z = (to == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_write_addr(uint8_t& r) {
|
auto SPC700::op_write_addr(reg r) {
|
||||||
dp.l = readPC();
|
dp.l = readPC();
|
||||||
dp.h = readPC();
|
dp.h = readPC();
|
||||||
read(dp);
|
read(dp);
|
||||||
write(dp, r);
|
write(dp, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_write_addri(uint8_t& i) {
|
auto SPC700::op_write_addri(reg i) {
|
||||||
dp.l = readPC();
|
dp.l = readPC();
|
||||||
dp.h = readPC();
|
dp.h = readPC();
|
||||||
io();
|
io();
|
||||||
|
@ -215,13 +215,13 @@ auto SPC700::op_write_addri(uint8_t& i) {
|
||||||
write(dp, regs.a);
|
write(dp, regs.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_write_dp(uint8_t& r) {
|
auto SPC700::op_write_dp(reg r) {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
readDP(dp);
|
readDP(dp);
|
||||||
writeDP(dp, r);
|
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;
|
dp = readPC() + i;
|
||||||
io();
|
io();
|
||||||
readDP(dp);
|
readDP(dp);
|
||||||
|
|
|
@ -1,51 +1,53 @@
|
||||||
struct Flag {
|
struct Flags {
|
||||||
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; }
|
|
||||||
|
|
||||||
union {
|
union {
|
||||||
uint16_t w;
|
uint8_t data = 0;
|
||||||
struct { uint8_t order_lsb2(l, h); };
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Regs {
|
inline operator uint() const { return data; }
|
||||||
Word pc;
|
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 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 {
|
union {
|
||||||
uint16_t ya;
|
uint16_t ya;
|
||||||
struct { uint8_t order_lsb2(a, y); };
|
struct { uint8_t order_lsb2(a, y); };
|
||||||
};
|
};
|
||||||
uint8_t x, s;
|
uint8_t x, s;
|
||||||
Flag p;
|
Flags p;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,14 +4,7 @@ auto SPC700::serialize(serializer& s) -> void {
|
||||||
s.integer(regs.x);
|
s.integer(regs.x);
|
||||||
s.integer(regs.y);
|
s.integer(regs.y);
|
||||||
s.integer(regs.s);
|
s.integer(regs.s);
|
||||||
s.integer(regs.p.n);
|
s.integer(regs.p.data);
|
||||||
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(opcode);
|
s.integer(opcode);
|
||||||
s.integer(dp.w);
|
s.integer(dp.w);
|
||||||
|
|
|
@ -45,7 +45,7 @@ auto SPC700::instruction() -> void {
|
||||||
op(0x1d, adjust, fp(dec), regs.x)
|
op(0x1d, adjust, fp(dec), regs.x)
|
||||||
op(0x1e, read_addr, fp(cmp), regs.x)
|
op(0x1e, read_addr, fp(cmp), regs.x)
|
||||||
op(0x1f, jmp_iaddrx)
|
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(0x21, jst)
|
||||||
op(0x22, set_bit)
|
op(0x22, set_bit)
|
||||||
op(0x23, branch_bit)
|
op(0x23, branch_bit)
|
||||||
|
@ -77,7 +77,7 @@ auto SPC700::instruction() -> void {
|
||||||
op(0x3d, adjust, fp(inc), regs.x)
|
op(0x3d, adjust, fp(inc), regs.x)
|
||||||
op(0x3e, read_dp, fp(cmp), regs.x)
|
op(0x3e, read_dp, fp(cmp), regs.x)
|
||||||
op(0x3f, jsr_addr)
|
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(0x41, jst)
|
||||||
op(0x42, set_bit)
|
op(0x42, set_bit)
|
||||||
op(0x43, branch_bit)
|
op(0x43, branch_bit)
|
||||||
|
@ -109,7 +109,7 @@ auto SPC700::instruction() -> void {
|
||||||
op(0x5d, transfer, regs.a, regs.x)
|
op(0x5d, transfer, regs.a, regs.x)
|
||||||
op(0x5e, read_addr, fp(cmp), regs.y)
|
op(0x5e, read_addr, fp(cmp), regs.y)
|
||||||
op(0x5f, jmp_addr)
|
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(0x61, jst)
|
||||||
op(0x62, set_bit)
|
op(0x62, set_bit)
|
||||||
op(0x63, branch_bit)
|
op(0x63, branch_bit)
|
||||||
|
@ -141,7 +141,7 @@ auto SPC700::instruction() -> void {
|
||||||
op(0x7d, transfer, regs.x, regs.a)
|
op(0x7d, transfer, regs.x, regs.a)
|
||||||
op(0x7e, read_dp, fp(cmp), regs.y)
|
op(0x7e, read_dp, fp(cmp), regs.y)
|
||||||
op(0x7f, rti)
|
op(0x7f, rti)
|
||||||
op(0x80, set_flag, regs.p.c, 1)
|
op(0x80, set_flag, regs.p.c.bit, 1)
|
||||||
op(0x81, jst)
|
op(0x81, jst)
|
||||||
op(0x82, set_bit)
|
op(0x82, set_bit)
|
||||||
op(0x83, branch_bit)
|
op(0x83, branch_bit)
|
||||||
|
@ -173,7 +173,7 @@ auto SPC700::instruction() -> void {
|
||||||
op(0x9d, transfer, regs.s, regs.x)
|
op(0x9d, transfer, regs.s, regs.x)
|
||||||
op(0x9e, div_ya_x)
|
op(0x9e, div_ya_x)
|
||||||
op(0x9f, xcn)
|
op(0x9f, xcn)
|
||||||
op(0xa0, set_flag, regs.p.i, 1)
|
op(0xa0, set_flag, regs.p.i.bit, 1)
|
||||||
op(0xa1, jst)
|
op(0xa1, jst)
|
||||||
op(0xa2, set_bit)
|
op(0xa2, set_bit)
|
||||||
op(0xa3, branch_bit)
|
op(0xa3, branch_bit)
|
||||||
|
@ -205,7 +205,7 @@ auto SPC700::instruction() -> void {
|
||||||
op(0xbd, transfer, regs.x, regs.s)
|
op(0xbd, transfer, regs.x, regs.s)
|
||||||
op(0xbe, das)
|
op(0xbe, das)
|
||||||
op(0xbf, lda_ixinc)
|
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(0xc1, jst)
|
||||||
op(0xc2, set_bit)
|
op(0xc2, set_bit)
|
||||||
op(0xc3, branch_bit)
|
op(0xc3, branch_bit)
|
||||||
|
|
|
@ -17,14 +17,15 @@ struct SPC700 {
|
||||||
#include "registers.hpp"
|
#include "registers.hpp"
|
||||||
#include "memory.hpp"
|
#include "memory.hpp"
|
||||||
|
|
||||||
Regs regs;
|
Registers regs;
|
||||||
Word dp, sp, rd, wr, bit, ya;
|
Register dp, sp, rd, wr, bit, ya;
|
||||||
uint8 opcode;
|
uint8 opcode;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using fps = auto (SPC700::*)(uint8) -> uint8;
|
using fps = auto (SPC700::*)(uint8) -> uint8;
|
||||||
using fpb = auto (SPC700::*)(uint8, uint8) -> uint8;
|
using fpb = auto (SPC700::*)(uint8, uint8) -> uint8;
|
||||||
using fpw = auto (SPC700::*)(uint16, uint16) -> uint16;
|
using fpw = auto (SPC700::*)(uint16, uint16) -> uint16;
|
||||||
|
using reg = uint8_t&;
|
||||||
|
|
||||||
auto op_adc(uint8, uint8) -> uint8;
|
auto op_adc(uint8, uint8) -> uint8;
|
||||||
auto op_and(uint8, uint8) -> uint8;
|
auto op_and(uint8, uint8) -> uint8;
|
||||||
|
@ -45,33 +46,33 @@ protected:
|
||||||
auto op_ldw(uint16, uint16) -> uint16;
|
auto op_ldw(uint16, uint16) -> uint16;
|
||||||
auto op_sbw(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_addr(fps);
|
||||||
auto op_adjust_dp(fps);
|
auto op_adjust_dp(fps);
|
||||||
auto op_adjust_dpw(int);
|
auto op_adjust_dpw(int);
|
||||||
auto op_adjust_dpx(fps);
|
auto op_adjust_dpx(fps);
|
||||||
auto op_branch(bool);
|
auto op_branch(bool);
|
||||||
auto op_branch_bit();
|
auto op_branch_bit();
|
||||||
auto op_pull(uint8_t&);
|
auto op_pull(reg);
|
||||||
auto op_push(uint8);
|
auto op_push(uint8);
|
||||||
auto op_read_addr(fpb, uint8_t&);
|
auto op_read_addr(fpb, reg);
|
||||||
auto op_read_addri(fpb, uint8_t&);
|
auto op_read_addri(fpb, reg);
|
||||||
auto op_read_const(fpb, uint8_t&);
|
auto op_read_const(fpb, reg);
|
||||||
auto op_read_dp(fpb, uint8_t&);
|
auto op_read_dp(fpb, reg);
|
||||||
auto op_read_dpi(fpb, uint8_t&, uint8_t&);
|
auto op_read_dpi(fpb, reg, reg);
|
||||||
auto op_read_dpw(fpw);
|
auto op_read_dpw(fpw);
|
||||||
auto op_read_idpx(fpb);
|
auto op_read_idpx(fpb);
|
||||||
auto op_read_idpy(fpb);
|
auto op_read_idpy(fpb);
|
||||||
auto op_read_ix(fpb);
|
auto op_read_ix(fpb);
|
||||||
auto op_set_addr_bit();
|
auto op_set_addr_bit();
|
||||||
auto op_set_bit();
|
auto op_set_bit();
|
||||||
auto op_set_flag(bool&, bool);
|
auto op_set_flag(uint, bool);
|
||||||
auto op_test_addr(bool);
|
auto op_test_addr(bool);
|
||||||
auto op_transfer(uint8_t&, uint8_t&);
|
auto op_transfer(reg, reg);
|
||||||
auto op_write_addr(uint8_t&);
|
auto op_write_addr(reg);
|
||||||
auto op_write_addri(uint8_t&);
|
auto op_write_addri(reg);
|
||||||
auto op_write_dp(uint8_t&);
|
auto op_write_dp(reg);
|
||||||
auto op_write_dpi(uint8_t&, uint8_t&);
|
auto op_write_dpi(reg, reg);
|
||||||
auto op_write_dp_const(fpb);
|
auto op_write_dp_const(fpb);
|
||||||
auto op_write_dp_dp(fpb);
|
auto op_write_dp_dp(fpb);
|
||||||
auto op_write_ix_iy(fpb);
|
auto op_write_ix_iy(fpb);
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -14,35 +14,13 @@ auto uPD96050::serialize(serializer& s) -> void {
|
||||||
s.integer(regs.a);
|
s.integer(regs.a);
|
||||||
s.integer(regs.b);
|
s.integer(regs.b);
|
||||||
|
|
||||||
s.integer(regs.flaga.s1);
|
s.integer(regs.flaga.data);
|
||||||
s.integer(regs.flaga.s0);
|
s.integer(regs.flagb.data);
|
||||||
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.tr);
|
s.integer(regs.tr);
|
||||||
s.integer(regs.trb);
|
s.integer(regs.trb);
|
||||||
|
|
||||||
s.integer(regs.sr.rqm);
|
s.integer(regs.sr.data);
|
||||||
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.dr);
|
s.integer(regs.dr);
|
||||||
s.integer(regs.si);
|
s.integer(regs.si);
|
||||||
s.integer(regs.so);
|
s.integer(regs.so);
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
namespace Processor {
|
namespace Processor {
|
||||||
|
|
||||||
#include "registers.cpp"
|
|
||||||
#include "instructions.cpp"
|
#include "instructions.cpp"
|
||||||
#include "memory.cpp"
|
#include "memory.cpp"
|
||||||
#include "disassembler.cpp"
|
#include "disassembler.cpp"
|
||||||
|
|
|
@ -32,19 +32,40 @@ struct uPD96050 {
|
||||||
uint16 dataROM[2048];
|
uint16 dataROM[2048];
|
||||||
uint16 dataRAM[2048];
|
uint16 dataRAM[2048];
|
||||||
|
|
||||||
//registers.cpp
|
|
||||||
struct Flag {
|
struct Flag {
|
||||||
inline operator uint() const;
|
union {
|
||||||
inline auto operator=(uint d) -> uint;
|
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 {
|
struct Status {
|
||||||
inline operator uint() const;
|
union {
|
||||||
inline auto operator=(uint d) -> uint;
|
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 {
|
struct Regs {
|
||||||
|
|
|
@ -16,13 +16,13 @@ auto V30MZ::opComplementCarry() {
|
||||||
r.f.c = !r.f.c;
|
r.f.c = !r.f.c;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto V30MZ::opClearFlag(bool& flag) {
|
auto V30MZ::opClearFlag(uint bit) {
|
||||||
wait(3);
|
wait(3);
|
||||||
flag = false;
|
r.f &= ~(1 << bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto V30MZ::opSetFlag(bool& flag) {
|
auto V30MZ::opSetFlag(uint bit) {
|
||||||
wait(3);
|
wait(3);
|
||||||
flag = true;
|
r.f |= 1 << bit;
|
||||||
if(&flag == &r.f.i) state.poll = false;
|
if(bit == r.f.i.bit) state.poll = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,26 +28,3 @@ auto V30MZ::setAcc(Size size, uint32 data) -> void {
|
||||||
if(size == Word) r.ax = data;
|
if(size == Word) r.ax = data;
|
||||||
if(size == Long) r.ax = data, r.dx = data >> 16;
|
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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -38,14 +38,5 @@ auto V30MZ::serialize(serializer& s) -> void {
|
||||||
s.integer(r.ss);
|
s.integer(r.ss);
|
||||||
s.integer(r.ds);
|
s.integer(r.ds);
|
||||||
s.integer(r.ip);
|
s.integer(r.ip);
|
||||||
s.integer(r.f.m);
|
s.integer(r.f.data);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -333,12 +333,12 @@ auto V30MZ::instruction() -> void {
|
||||||
case 0xf5: return opComplementCarry();
|
case 0xf5: return opComplementCarry();
|
||||||
case 0xf6: return opGroup3MemImm(Byte);
|
case 0xf6: return opGroup3MemImm(Byte);
|
||||||
case 0xf7: return opGroup3MemImm(Word);
|
case 0xf7: return opGroup3MemImm(Word);
|
||||||
case 0xf8: return opClearFlag(r.f.c);
|
case 0xf8: return opClearFlag(r.f.c.bit);
|
||||||
case 0xf9: return opSetFlag(r.f.c);
|
case 0xf9: return opSetFlag(r.f.c.bit);
|
||||||
case 0xfa: return opClearFlag(r.f.i);
|
case 0xfa: return opClearFlag(r.f.i.bit);
|
||||||
case 0xfb: return opSetFlag(r.f.i);
|
case 0xfb: return opSetFlag(r.f.i.bit);
|
||||||
case 0xfc: return opClearFlag(r.f.d);
|
case 0xfc: return opClearFlag(r.f.d.bit);
|
||||||
case 0xfd: return opSetFlag(r.f.d);
|
case 0xfd: return opSetFlag(r.f.d.bit);
|
||||||
case 0xfe: return opGroup4MemImm(Byte);
|
case 0xfe: return opGroup4MemImm(Byte);
|
||||||
case 0xff: return opGroup4MemImm(Word);
|
case 0xff: return opGroup4MemImm(Word);
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,8 +156,8 @@ struct V30MZ {
|
||||||
auto opStoreFlagsAcc();
|
auto opStoreFlagsAcc();
|
||||||
auto opLoadAccFlags();
|
auto opLoadAccFlags();
|
||||||
auto opComplementCarry();
|
auto opComplementCarry();
|
||||||
auto opClearFlag(bool&);
|
auto opClearFlag(uint);
|
||||||
auto opSetFlag(bool&);
|
auto opSetFlag(uint);
|
||||||
|
|
||||||
//instructions-group.cpp
|
//instructions-group.cpp
|
||||||
auto opGroup1MemImm(Size, bool);
|
auto opGroup1MemImm(Size, bool);
|
||||||
|
@ -247,20 +247,25 @@ struct V30MZ {
|
||||||
uint16_t* s[8]{&es, &cs, &ss, &ds, &es, &cs, &ss, &ds};
|
uint16_t* s[8]{&es, &cs, &ss, &ds, &es, &cs, &ss, &ds};
|
||||||
|
|
||||||
struct Flags {
|
struct Flags {
|
||||||
//registers.cpp
|
union {
|
||||||
operator uint16_t() const;
|
uint16_t data = 0;
|
||||||
auto operator=(uint16_t data);
|
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
|
operator uint() const { return data & 0x8fd5 | 0x7002; }
|
||||||
bool v; //overflow
|
auto& operator =(uint value) { return data = value, *this; }
|
||||||
bool d; //direction
|
auto& operator&=(uint value) { return data &= value, *this; }
|
||||||
bool i; //interrupt
|
auto& operator|=(uint value) { return data |= value, *this; }
|
||||||
bool b; //break
|
auto& operator^=(uint value) { return data ^= value, *this; }
|
||||||
bool s; //sign
|
|
||||||
bool z; //zero
|
|
||||||
bool h; //half-carry
|
|
||||||
bool p; //parity
|
|
||||||
bool c; //carry
|
|
||||||
} f;
|
} f;
|
||||||
} r;
|
} r;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -17,7 +17,8 @@
|
||||||
#include <nall/any.hpp>
|
#include <nall/any.hpp>
|
||||||
#include <nall/atoi.hpp>
|
#include <nall/atoi.hpp>
|
||||||
#include <nall/bit.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/config.hpp>
|
||||||
#include <nall/directory.hpp>
|
#include <nall/directory.hpp>
|
||||||
#include <nall/dl.hpp>
|
#include <nall/dl.hpp>
|
||||||
|
|
|
@ -5,52 +5,6 @@
|
||||||
|
|
||||||
namespace nall {
|
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 {
|
struct Boolean {
|
||||||
inline Boolean() : data(false) {}
|
inline Boolean() : data(false) {}
|
||||||
template<typename T> inline Boolean(const T& value) : data(value) {}
|
template<typename T> inline Boolean(const T& value) : data(value) {}
|
||||||
|
|
Loading…
Reference in New Issue