mirror of https://github.com/bsnes-emu/bsnes.git
425 lines
9.8 KiB
C++
425 lines
9.8 KiB
C++
//$00 stop
|
|
auto GSU::instructionSTOP() -> void {
|
|
if(regs.cfgr.irq == 0) {
|
|
regs.sfr.irq = 1;
|
|
stop();
|
|
}
|
|
regs.sfr.g = 0;
|
|
regs.pipeline = 0x01; //nop
|
|
regs.reset();
|
|
}
|
|
|
|
//$01 nop
|
|
auto GSU::instructionNOP() -> void {
|
|
regs.reset();
|
|
}
|
|
|
|
//$02 cache
|
|
auto GSU::instructionCACHE() -> void {
|
|
if(regs.cbr != (regs.r[15] & 0xfff0)) {
|
|
regs.cbr = regs.r[15] & 0xfff0;
|
|
flushCache();
|
|
}
|
|
regs.reset();
|
|
}
|
|
|
|
//$03 lsr
|
|
auto GSU::instructionLSR() -> void {
|
|
regs.sfr.cy = (regs.sr() & 1);
|
|
regs.dr() = regs.sr() >> 1;
|
|
regs.sfr.s = (regs.dr() & 0x8000);
|
|
regs.sfr.z = (regs.dr() == 0);
|
|
regs.reset();
|
|
}
|
|
|
|
//$04 rol
|
|
auto GSU::instructionROL() -> void {
|
|
bool carry = (regs.sr() & 0x8000);
|
|
regs.dr() = (regs.sr() << 1) | regs.sfr.cy;
|
|
regs.sfr.s = (regs.dr() & 0x8000);
|
|
regs.sfr.cy = carry;
|
|
regs.sfr.z = (regs.dr() == 0);
|
|
regs.reset();
|
|
}
|
|
|
|
//$05 bra e
|
|
//$06 blt e
|
|
//$07 bge e
|
|
//$08 bne e
|
|
//$09 beq e
|
|
//$0a bpl e
|
|
//$0b bmi e
|
|
//$0c bcc e
|
|
//$0d bcs e
|
|
//$0e bvc e
|
|
//$0f bvs e
|
|
auto GSU::instructionBranch(bool take) -> void {
|
|
auto displacement = (int8)pipe();
|
|
if(take) regs.r[15] += displacement;
|
|
}
|
|
|
|
//$10-1f(b0) to rN
|
|
//$10-1f(b1) move rN
|
|
auto GSU::instructionTO_MOVE(uint n) -> void {
|
|
if(!regs.sfr.b) {
|
|
regs.dreg = n;
|
|
} else {
|
|
regs.r[n] = regs.sr();
|
|
regs.reset();
|
|
}
|
|
}
|
|
|
|
//$20-2f with rN
|
|
auto GSU::instructionWITH(uint n) -> void {
|
|
regs.sreg = n;
|
|
regs.dreg = n;
|
|
regs.sfr.b = 1;
|
|
}
|
|
|
|
//$30-3b(alt0) stw (rN)
|
|
//$30-3b(alt1) stb (rN)
|
|
auto GSU::instructionStore(uint n) -> void {
|
|
regs.ramaddr = regs.r[n];
|
|
writeRAMBuffer(regs.ramaddr, regs.sr());
|
|
if(!regs.sfr.alt1) writeRAMBuffer(regs.ramaddr ^ 1, regs.sr() >> 8);
|
|
regs.reset();
|
|
}
|
|
|
|
//$3c loop
|
|
auto GSU::instructionLOOP() -> void {
|
|
regs.r[12]--;
|
|
regs.sfr.s = (regs.r[12] & 0x8000);
|
|
regs.sfr.z = (regs.r[12] == 0);
|
|
if(!regs.sfr.z) regs.r[15] = regs.r[13];
|
|
regs.reset();
|
|
}
|
|
|
|
//$3d alt1
|
|
auto GSU::instructionALT1() -> void {
|
|
regs.sfr.b = 0;
|
|
regs.sfr.alt1 = 1;
|
|
}
|
|
|
|
//$3e alt2
|
|
auto GSU::instructionALT2() -> void {
|
|
regs.sfr.b = 0;
|
|
regs.sfr.alt2 = 1;
|
|
}
|
|
|
|
//$3f alt3
|
|
auto GSU::instructionALT3() -> void {
|
|
regs.sfr.b = 0;
|
|
regs.sfr.alt1 = 1;
|
|
regs.sfr.alt2 = 1;
|
|
}
|
|
|
|
//$40-4b(alt0) ldw (rN)
|
|
//$40-4b(alt1) ldb (rN)
|
|
auto GSU::instructionLoad(uint n) -> void {
|
|
regs.ramaddr = regs.r[n];
|
|
regs.dr() = readRAMBuffer(regs.ramaddr);
|
|
if(!regs.sfr.alt1) regs.dr() |= readRAMBuffer(regs.ramaddr ^ 1) << 8;
|
|
regs.reset();
|
|
}
|
|
|
|
//$4c(alt0) plot
|
|
//$4c(alt1) rpix
|
|
auto GSU::instructionPLOT_RPIX() -> void {
|
|
if(!regs.sfr.alt1) {
|
|
plot(regs.r[1], regs.r[2]);
|
|
regs.r[1]++;
|
|
} else {
|
|
regs.dr() = rpix(regs.r[1], regs.r[2]);
|
|
regs.sfr.s = (regs.dr() & 0x8000);
|
|
regs.sfr.z = (regs.dr() == 0);
|
|
}
|
|
regs.reset();
|
|
}
|
|
|
|
//$4d swap
|
|
auto GSU::instructionSWAP() -> void {
|
|
regs.dr() = regs.sr() >> 8 | regs.sr() << 8;
|
|
regs.sfr.s = (regs.dr() & 0x8000);
|
|
regs.sfr.z = (regs.dr() == 0);
|
|
regs.reset();
|
|
}
|
|
|
|
//$4e(alt0) color
|
|
//$4e(alt1) cmode
|
|
auto GSU::instructionCOLOR_CMODE() -> void {
|
|
if(!regs.sfr.alt1) {
|
|
regs.colr = color(regs.sr());
|
|
} else {
|
|
regs.por = regs.sr();
|
|
}
|
|
regs.reset();
|
|
}
|
|
|
|
//$4f not
|
|
auto GSU::instructionNOT() -> void {
|
|
regs.dr() = ~regs.sr();
|
|
regs.sfr.s = (regs.dr() & 0x8000);
|
|
regs.sfr.z = (regs.dr() == 0);
|
|
regs.reset();
|
|
}
|
|
|
|
//$50-5f(alt0) add rN
|
|
//$50-5f(alt1) adc rN
|
|
//$50-5f(alt2) add #N
|
|
//$50-5f(alt3) adc #N
|
|
auto GSU::instructionADD_ADC(uint n) -> void {
|
|
if(!regs.sfr.alt2) n = regs.r[n];
|
|
int r = regs.sr() + n + (regs.sfr.alt1 ? regs.sfr.cy : 0);
|
|
regs.sfr.ov = ~(regs.sr() ^ n) & (n ^ r) & 0x8000;
|
|
regs.sfr.s = (r & 0x8000);
|
|
regs.sfr.cy = (r >= 0x10000);
|
|
regs.sfr.z = ((uint16)r == 0);
|
|
regs.dr() = r;
|
|
regs.reset();
|
|
}
|
|
|
|
//$60-6f(alt0) sub rN
|
|
//$60-6f(alt1) sbc rN
|
|
//$60-6f(alt2) sub #N
|
|
//$60-6f(alt3) cmp rN
|
|
auto GSU::instructionSUB_SBC_CMP(uint n) -> void {
|
|
if(!regs.sfr.alt2 || regs.sfr.alt1) n = regs.r[n];
|
|
int r = regs.sr() - n - (!regs.sfr.alt2 && regs.sfr.alt1 ? !regs.sfr.cy : 0);
|
|
regs.sfr.ov = (regs.sr() ^ n) & (regs.sr() ^ r) & 0x8000;
|
|
regs.sfr.s = (r & 0x8000);
|
|
regs.sfr.cy = (r >= 0);
|
|
regs.sfr.z = ((uint16)r == 0);
|
|
if(!regs.sfr.alt2 || !regs.sfr.alt1) regs.dr() = r;
|
|
regs.reset();
|
|
}
|
|
|
|
//$70 merge
|
|
auto GSU::instructionMERGE() -> void {
|
|
regs.dr() = (regs.r[7] & 0xff00) | (regs.r[8] >> 8);
|
|
regs.sfr.ov = (regs.dr() & 0xc0c0);
|
|
regs.sfr.s = (regs.dr() & 0x8080);
|
|
regs.sfr.cy = (regs.dr() & 0xe0e0);
|
|
regs.sfr.z = (regs.dr() & 0xf0f0);
|
|
regs.reset();
|
|
}
|
|
|
|
//$71-7f(alt0) and rN
|
|
//$71-7f(alt1) bic rN
|
|
//$71-7f(alt2) and #N
|
|
//$71-7f(alt3) bic #N
|
|
auto GSU::instructionAND_BIC(uint n) -> void {
|
|
if(!regs.sfr.alt2) n = regs.r[n];
|
|
regs.dr() = regs.sr() & (regs.sfr.alt1 ? ~n : n);
|
|
regs.sfr.s = (regs.dr() & 0x8000);
|
|
regs.sfr.z = (regs.dr() == 0);
|
|
regs.reset();
|
|
}
|
|
|
|
//$80-8f(alt0) mult rN
|
|
//$80-8f(alt1) umult rN
|
|
//$80-8f(alt2) mult #N
|
|
//$80-8f(alt3) umult #N
|
|
auto GSU::instructionMULT_UMULT(uint n) -> void {
|
|
if(!regs.sfr.alt2) n = regs.r[n];
|
|
regs.dr() = (!regs.sfr.alt1 ? ((int8)regs.sr() * (int8)n) : ((uint8)regs.sr() * (uint8)n));
|
|
regs.sfr.s = (regs.dr() & 0x8000);
|
|
regs.sfr.z = (regs.dr() == 0);
|
|
regs.reset();
|
|
if(!regs.cfgr.ms0) step(regs.clsr ? 1 : 2);
|
|
}
|
|
|
|
//$90 sbk
|
|
auto GSU::instructionSBK() -> void {
|
|
writeRAMBuffer(regs.ramaddr ^ 0, regs.sr() >> 0);
|
|
writeRAMBuffer(regs.ramaddr ^ 1, regs.sr() >> 8);
|
|
regs.reset();
|
|
}
|
|
|
|
//$91-94 link #N
|
|
auto GSU::instructionLINK(uint n) -> void {
|
|
regs.r[11] = regs.r[15] + n;
|
|
regs.reset();
|
|
}
|
|
|
|
//$95 sex
|
|
auto GSU::instructionSEX() -> void {
|
|
regs.dr() = (int8)regs.sr();
|
|
regs.sfr.s = (regs.dr() & 0x8000);
|
|
regs.sfr.z = (regs.dr() == 0);
|
|
regs.reset();
|
|
}
|
|
|
|
//$96(alt0) asr
|
|
//$96(alt1) div2
|
|
auto GSU::instructionASR_DIV2() -> void {
|
|
regs.sfr.cy = (regs.sr() & 1);
|
|
regs.dr() = ((int16)regs.sr() >> 1) + (regs.sfr.alt1 ? ((regs.sr() + 1) >> 16) : 0);
|
|
regs.sfr.s = (regs.dr() & 0x8000);
|
|
regs.sfr.z = (regs.dr() == 0);
|
|
regs.reset();
|
|
}
|
|
|
|
//$97 ror
|
|
auto GSU::instructionROR() -> void {
|
|
bool carry = (regs.sr() & 1);
|
|
regs.dr() = (regs.sfr.cy << 15) | (regs.sr() >> 1);
|
|
regs.sfr.s = (regs.dr() & 0x8000);
|
|
regs.sfr.cy = carry;
|
|
regs.sfr.z = (regs.dr() == 0);
|
|
regs.reset();
|
|
}
|
|
|
|
//$98-9d(alt0) jmp rN
|
|
//$98-9d(alt1) ljmp rN
|
|
auto GSU::instructionJMP_LJMP(uint n) -> void {
|
|
if(!regs.sfr.alt1) {
|
|
regs.r[15] = regs.r[n];
|
|
} else {
|
|
regs.pbr = regs.r[n] & 0x7f;
|
|
regs.r[15] = regs.sr();
|
|
regs.cbr = regs.r[15] & 0xfff0;
|
|
flushCache();
|
|
}
|
|
regs.reset();
|
|
}
|
|
|
|
//$9e lob
|
|
auto GSU::instructionLOB() -> void {
|
|
regs.dr() = regs.sr() & 0xff;
|
|
regs.sfr.s = (regs.dr() & 0x80);
|
|
regs.sfr.z = (regs.dr() == 0);
|
|
regs.reset();
|
|
}
|
|
|
|
//$9f(alt0) fmult
|
|
//$9f(alt1) lmult
|
|
auto GSU::instructionFMULT_LMULT() -> void {
|
|
uint32 result = (int16)regs.sr() * (int16)regs.r[6];
|
|
if(regs.sfr.alt1) regs.r[4] = result;
|
|
regs.dr() = result >> 16;
|
|
regs.sfr.s = (regs.dr() & 0x8000);
|
|
regs.sfr.cy = (result & 0x8000);
|
|
regs.sfr.z = (regs.dr() == 0);
|
|
regs.reset();
|
|
step((regs.cfgr.ms0 ? 3 : 7) * (regs.clsr ? 1 : 2));
|
|
}
|
|
|
|
//$a0-af(alt0) ibt rN,#pp
|
|
//$a0-af(alt1) lms rN,(yy)
|
|
//$a0-af(alt2) sms (yy),rN
|
|
auto GSU::instructionIBT_LMS_SMS(uint n) -> void {
|
|
if(regs.sfr.alt1) {
|
|
regs.ramaddr = pipe() << 1;
|
|
uint8 lo = readRAMBuffer(regs.ramaddr ^ 0) << 0;
|
|
regs.r[n] = readRAMBuffer(regs.ramaddr ^ 1) << 8 | lo;
|
|
} else if(regs.sfr.alt2) {
|
|
regs.ramaddr = pipe() << 1;
|
|
writeRAMBuffer(regs.ramaddr ^ 0, regs.r[n] >> 0);
|
|
writeRAMBuffer(regs.ramaddr ^ 1, regs.r[n] >> 8);
|
|
} else {
|
|
regs.r[n] = (int8)pipe();
|
|
}
|
|
regs.reset();
|
|
}
|
|
|
|
//$b0-bf(b0) from rN
|
|
//$b0-bf(b1) moves rN
|
|
auto GSU::instructionFROM_MOVES(uint n) -> void {
|
|
if(!regs.sfr.b) {
|
|
regs.sreg = n;
|
|
} else {
|
|
regs.dr() = regs.r[n];
|
|
regs.sfr.ov = (regs.dr() & 0x80);
|
|
regs.sfr.s = (regs.dr() & 0x8000);
|
|
regs.sfr.z = (regs.dr() == 0);
|
|
regs.reset();
|
|
}
|
|
}
|
|
|
|
//$c0 hib
|
|
auto GSU::instructionHIB() -> void {
|
|
regs.dr() = regs.sr() >> 8;
|
|
regs.sfr.s = (regs.dr() & 0x80);
|
|
regs.sfr.z = (regs.dr() == 0);
|
|
regs.reset();
|
|
}
|
|
|
|
//$c1-cf(alt0) or rN
|
|
//$c1-cf(alt1) xor rN
|
|
//$c1-cf(alt2) or #N
|
|
//$c1-cf(alt3) xor #N
|
|
auto GSU::instructionOR_XOR(uint n) -> void {
|
|
if(!regs.sfr.alt2) n = regs.r[n];
|
|
regs.dr() = (!regs.sfr.alt1 ? (regs.sr() | n) : (regs.sr() ^ n));
|
|
regs.sfr.s = (regs.dr() & 0x8000);
|
|
regs.sfr.z = (regs.dr() == 0);
|
|
regs.reset();
|
|
}
|
|
|
|
//$d0-de inc rN
|
|
auto GSU::instructionINC(uint n) -> void {
|
|
regs.r[n]++;
|
|
regs.sfr.s = (regs.r[n] & 0x8000);
|
|
regs.sfr.z = (regs.r[n] == 0);
|
|
regs.reset();
|
|
}
|
|
|
|
//$df(alt0) getc
|
|
//$df(alt2) ramb
|
|
//$df(alt3) romb
|
|
auto GSU::instructionGETC_RAMB_ROMB() -> void {
|
|
if(!regs.sfr.alt2) {
|
|
regs.colr = color(readROMBuffer());
|
|
} else if(!regs.sfr.alt1) {
|
|
syncRAMBuffer();
|
|
regs.rambr = regs.sr() & 0x01;
|
|
} else {
|
|
syncROMBuffer();
|
|
regs.rombr = regs.sr() & 0x7f;
|
|
}
|
|
regs.reset();
|
|
}
|
|
|
|
//$e0-ee dec rN
|
|
auto GSU::instructionDEC(uint n) -> void {
|
|
regs.r[n]--;
|
|
regs.sfr.s = (regs.r[n] & 0x8000);
|
|
regs.sfr.z = (regs.r[n] == 0);
|
|
regs.reset();
|
|
}
|
|
|
|
//$ef(alt0) getb
|
|
//$ef(alt1) getbh
|
|
//$ef(alt2) getbl
|
|
//$ef(alt3) getbs
|
|
auto GSU::instructionGETB() -> void {
|
|
switch(regs.sfr.alt2 << 1 | regs.sfr.alt1 << 0) {
|
|
case 0: regs.dr() = readROMBuffer(); break;
|
|
case 1: regs.dr() = readROMBuffer() << 8 | (uint8)regs.sr(); break;
|
|
case 2: regs.dr() = (regs.sr() & 0xff00) | readROMBuffer(); break;
|
|
case 3: regs.dr() = (int8)readROMBuffer(); break;
|
|
}
|
|
regs.reset();
|
|
}
|
|
|
|
//$f0-ff(alt0) iwt rN,#xx
|
|
//$f0-ff(alt1) lm rN,(xx)
|
|
//$f0-ff(alt2) sm (xx),rN
|
|
auto GSU::instructionIWT_LM_SM(uint n) -> void {
|
|
if(regs.sfr.alt1) {
|
|
regs.ramaddr = pipe() << 0;
|
|
regs.ramaddr |= pipe() << 8;
|
|
uint8 lo = readRAMBuffer(regs.ramaddr ^ 0) << 0;
|
|
regs.r[n] = readRAMBuffer(regs.ramaddr ^ 1) << 8 | lo;
|
|
} else if(regs.sfr.alt2) {
|
|
regs.ramaddr = pipe() << 0;
|
|
regs.ramaddr |= pipe() << 8;
|
|
writeRAMBuffer(regs.ramaddr ^ 0, regs.r[n] >> 0);
|
|
writeRAMBuffer(regs.ramaddr ^ 1, regs.r[n] >> 8);
|
|
} else {
|
|
uint8 lo = pipe();
|
|
regs.r[n] = pipe() << 8 | lo;
|
|
}
|
|
regs.reset();
|
|
}
|