2012-03-19 11:19:53 +00:00
|
|
|
struct GPR {
|
|
|
|
uint32 data;
|
|
|
|
function<void ()> modify;
|
|
|
|
|
|
|
|
inline operator uint32() const { return data; }
|
|
|
|
inline GPR& operator=(uint32 n) { data = n; if(modify) modify(); return *this; }
|
2012-03-21 11:08:16 +00:00
|
|
|
inline GPR& operator=(const GPR& source) { return operator=(source.data); }
|
2012-03-19 11:19:53 +00:00
|
|
|
|
|
|
|
inline GPR& operator &=(uint32 n) { return operator=(data & n); }
|
|
|
|
inline GPR& operator |=(uint32 n) { return operator=(data | n); }
|
|
|
|
inline GPR& operator ^=(uint32 n) { return operator=(data ^ n); }
|
|
|
|
inline GPR& operator +=(uint32 n) { return operator=(data + n); }
|
|
|
|
inline GPR& operator -=(uint32 n) { return operator=(data - n); }
|
|
|
|
inline GPR& operator *=(uint32 n) { return operator=(data * n); }
|
|
|
|
inline GPR& operator /=(uint32 n) { return operator=(data / n); }
|
|
|
|
inline GPR& operator %=(uint32 n) { return operator=(data % n); }
|
|
|
|
inline GPR& operator<<=(uint32 n) { return operator=(data << n); }
|
|
|
|
inline GPR& operator>>=(uint32 n) { return operator=(data >> n); }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct PSR {
|
|
|
|
bool n; //negative
|
|
|
|
bool z; //zero
|
|
|
|
bool c; //carry
|
|
|
|
bool v; //overflow
|
|
|
|
bool i; //irq
|
|
|
|
bool f; //fiq
|
|
|
|
bool t; //thumb
|
|
|
|
unsigned m; //mode
|
|
|
|
|
|
|
|
inline operator uint32() const {
|
|
|
|
return (n << 31) + (z << 30) + (c << 29) + (v << 28)
|
2012-04-17 12:16:54 +00:00
|
|
|
+ (i << 7) + (f << 6) + (t << 5) + (m << 0);
|
2012-03-19 11:19:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline PSR& operator=(uint32 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;
|
|
|
|
}
|
Update to v087r26 release.
byuu says:
Changelog:
- fixed FIFO[1] reset behavior (fixes audio in Sword of Mana)
- added FlashROM emulation (both sizes)
- GBA parses RAM settings from manifest.xml now
- save RAM is written to disk now
- added save state support (it's currently broken, though)
- fixed ROM/RAM access timings
- open bus should mostly work (we don't do the PC+12 stuff yet)
- emulated the undocumented memory control register (mirror IWRAM,
disable I+EWRAM, EWRAM wait state count)
- emulated keypad interrupts
- emulated STOP (freezes video, audio, DMA and timers; only breaks on
keypad IRQs)
- probably a lot more, it was a long night ...
Show stoppers, missing things, broken things, etc:
- ST018 is still completely broken
- GBC audio sequencer apparently needs work
- GBA audio FIFO buffer seems too quiet
- PHI / ROM prefetch needs to be emulated (no idea on how to do this,
especially PHI)
- SOUNDBIAS 64/128/256khz modes should output at that resolution
(really, we need to simulate PWM properly, no idea on how to do this)
- object mosaic top-left coordinates are wrong (minor, fixing will
actually make the effect look worse)
- need to emulate PPU greenswap and color palette distortion (no idea on
how do this)
- need GBA save type database (I would also LIKE to blacklist
/ patch-out trainers, but that's a discussion for another day.)
- some ARM ops advance the prefetch buffer, so you can read PC+12 in
some cases
2012-04-16 12:19:39 +00:00
|
|
|
|
|
|
|
void serialize(serializer&);
|
2012-03-19 11:19:53 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Pipeline {
|
|
|
|
bool reload;
|
2012-03-21 11:08:16 +00:00
|
|
|
|
2012-03-19 11:19:53 +00:00
|
|
|
struct Instruction {
|
|
|
|
uint32 address;
|
2012-03-21 11:08:16 +00:00
|
|
|
uint32 instruction;
|
2012-03-19 11:19:53 +00:00
|
|
|
};
|
2012-03-21 11:08:16 +00:00
|
|
|
|
2012-03-19 11:19:53 +00:00
|
|
|
Instruction execute;
|
|
|
|
Instruction decode;
|
|
|
|
Instruction fetch;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Processor {
|
|
|
|
enum class Mode : unsigned {
|
|
|
|
USR = 0x10, //user
|
|
|
|
FIQ = 0x11, //fast interrupt request
|
|
|
|
IRQ = 0x12, //interrupt request
|
|
|
|
SVC = 0x13, //supervisor (software interrupt)
|
|
|
|
ABT = 0x17, //abort
|
|
|
|
UND = 0x1b, //undefined
|
|
|
|
SYS = 0x1f, //system
|
|
|
|
};
|
|
|
|
|
|
|
|
GPR r0, r1, r2, r3, r4, r5, r6, r7;
|
|
|
|
|
|
|
|
struct USR {
|
|
|
|
GPR r8, r9, r10, r11, r12, sp, lr;
|
|
|
|
} usr;
|
|
|
|
|
|
|
|
struct FIQ {
|
|
|
|
GPR r8, r9, r10, r11, r12, sp, lr;
|
|
|
|
PSR spsr;
|
|
|
|
} fiq;
|
|
|
|
|
|
|
|
struct IRQ {
|
|
|
|
GPR sp, lr;
|
|
|
|
PSR spsr;
|
|
|
|
} irq;
|
|
|
|
|
|
|
|
struct SVC {
|
|
|
|
GPR sp, lr;
|
|
|
|
PSR spsr;
|
|
|
|
} svc;
|
|
|
|
|
|
|
|
struct ABT {
|
|
|
|
GPR sp, lr;
|
|
|
|
PSR spsr;
|
|
|
|
} abt;
|
|
|
|
|
|
|
|
struct UND {
|
|
|
|
GPR sp, lr;
|
|
|
|
PSR spsr;
|
|
|
|
} und;
|
|
|
|
|
|
|
|
GPR pc;
|
|
|
|
PSR cpsr;
|
2012-03-21 11:08:16 +00:00
|
|
|
bool carryout;
|
2012-04-15 06:49:56 +00:00
|
|
|
bool sequential;
|
2012-03-29 11:58:10 +00:00
|
|
|
bool irqline;
|
2012-03-19 11:19:53 +00:00
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
GPR* r[16];
|
|
|
|
PSR* spsr;
|
2012-03-19 11:19:53 +00:00
|
|
|
|
|
|
|
void power();
|
|
|
|
void setMode(Mode);
|
|
|
|
};
|
|
|
|
|
|
|
|
Processor processor;
|
|
|
|
Pipeline pipeline;
|
2012-03-29 11:58:10 +00:00
|
|
|
bool crash;
|
|
|
|
|
|
|
|
void pipeline_step();
|
2012-03-19 11:19:53 +00:00
|
|
|
|
|
|
|
alwaysinline GPR& r(unsigned n) { return *processor.r[n]; }
|
|
|
|
alwaysinline PSR& cpsr() { return processor.cpsr; }
|
|
|
|
alwaysinline PSR& spsr() { return *processor.spsr; }
|
2012-03-21 11:08:16 +00:00
|
|
|
alwaysinline bool& carryout() { return processor.carryout; }
|
2012-04-15 06:49:56 +00:00
|
|
|
alwaysinline bool& sequential() { return processor.sequential; }
|
2012-03-21 11:08:16 +00:00
|
|
|
alwaysinline uint32 instruction() { return pipeline.execute.instruction; }
|
|
|
|
alwaysinline Processor::Mode mode() { return (Processor::Mode)processor.cpsr.m; }
|
2012-03-29 11:58:10 +00:00
|
|
|
alwaysinline bool privilegedmode() const { return (Processor::Mode)processor.cpsr.m != Processor::Mode::USR; }
|
|
|
|
alwaysinline bool exceptionmode() const { return privilegedmode() && (Processor::Mode)processor.cpsr.m != Processor::Mode::SYS; }
|