Path: blob/master/libsnes/bsnes/snes/chip/necdsp/necdsp.cpp
2 views
#include <snes/snes.hpp>12#define NECDSP_CPP3namespace SNES {45#include "memory.cpp"6#include "disassembler.cpp"7#include "serialization.cpp"8NECDSP necdsp;910//zero 01-sep-2014 - dont clobber these when reconstructing!11unsigned NECDSP::frequency;12uint24 NECDSP::programROM[16384];13uint16 NECDSP::dataROM[2048];14unsigned NECDSP::programROMSize;15unsigned NECDSP::dataROMSize;1617void NECDSP::Enter() { necdsp.enter(); }1819void NECDSP::enter() {20while(true) {21if(scheduler.sync == Scheduler::SynchronizeMode::All) {22scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);23}2425uint24 opcode = programROM[regs.pc++];26switch(opcode >> 22) {27case 0: exec_op(opcode); break;28case 1: exec_rt(opcode); break;29case 2: exec_jp(opcode); break;30case 3: exec_ld(opcode); break;31}3233int32 result = (int32)regs.k * regs.l; //sign + 30-bit result34regs.m = result >> 15; //store sign + top 15-bits35regs.n = result << 1; //store low 15-bits + zero3637step(1);38synchronize_cpu();39}40}4142void NECDSP::exec_op(uint24 opcode) {43uint2 pselect = opcode >> 20; //P select44uint4 alu = opcode >> 16; //ALU operation mode45uint1 asl = opcode >> 15; //accumulator select46uint2 dpl = opcode >> 13; //DP low modify47uint4 dphm = opcode >> 9; //DP high XOR modify48uint1 rpdcr = opcode >> 8; //RP decrement49uint4 src = opcode >> 4; //move source50uint4 dst = opcode >> 0; //move destination5152uint16 idb;53switch(src) {54case 0: idb = regs.trb; break;55case 1: idb = regs.a; break;56case 2: idb = regs.b; break;57case 3: idb = regs.tr; break;58case 4: idb = regs.dp; break;59case 5: idb = regs.rp; break;60case 6: idb = dataROM[regs.rp]; break;61case 7: idb = 0x8000 - regs.flaga.s1; break;62case 8: idb = regs.dr; regs.sr.rqm = 1; break;63case 9: idb = regs.dr; break;64case 10: idb = regs.sr; break;65case 11: idb = regs.si; break; //MSB66case 12: idb = regs.si; break; //LSB67case 13: idb = regs.k; break;68case 14: idb = regs.l; break;69case 15: idb = dataRAM[regs.dp]; break;70}7172if(alu) {73uint16 p, q, r;74Flag flag;75bool c;7677switch(pselect) {78case 0: p = dataRAM[regs.dp]; break;79case 1: p = idb; break;80case 2: p = regs.m; break;81case 3: p = regs.n; break;82}8384switch(asl) {85case 0: q = regs.a; flag = regs.flaga; c = regs.flagb.c; break;86case 1: q = regs.b; flag = regs.flagb; c = regs.flaga.c; break;87}8889switch(alu) {90case 1: r = q | p; break; //OR91case 2: r = q & p; break; //AND92case 3: r = q ^ p; break; //XOR93case 4: r = q - p; break; //SUB94case 5: r = q + p; break; //ADD95case 6: r = q - p - c; break; //SBB96case 7: r = q + p + c; break; //ADC97case 8: r = q - 1; p = 1; break; //DEC98case 9: r = q + 1; p = 1; break; //INC99case 10: r = ~q; break; //CMP100case 11: r = (q >> 1) | (q & 0x8000); break; //SHR1 (ASR)101case 12: r = (q << 1) | c; break; //SHL1 (ROL)102case 13: r = (q << 2) | 3; break; //SHL2103case 14: r = (q << 4) | 15; break; //SHL4104case 15: r = (q << 8) | (q >> 8); break; //XCHG105}106107flag.s0 = (r & 0x8000);108flag.z = (r == 0);109110switch(alu) {111case 1: case 2: case 3: case 10: case 13: case 14: case 15: {112flag.c = 0;113flag.ov0 = 0;114flag.ov1 = 0;115break;116}117case 4: case 5: case 6: case 7: case 8: case 9: {118if(alu & 1) {119//addition120flag.ov0 = (q ^ r) & ~(q ^ p) & 0x8000;121flag.c = (r < q);122} else {123//subtraction124flag.ov0 = (q ^ r) & (q ^ p) & 0x8000;125flag.c = (r > q);126}127if(flag.ov0) {128flag.s1 = flag.ov1 ^ !(r & 0x8000);129flag.ov1 = !flag.ov1;130}131break;132}133case 11: {134flag.c = q & 1;135flag.ov0 = 0;136flag.ov1 = 0;137break;138}139case 12: {140flag.c = q >> 15;141flag.ov0 = 0;142flag.ov1 = 0;143break;144}145}146147switch(asl) {148case 0: regs.a = r; regs.flaga = flag; break;149case 1: regs.b = r; regs.flagb = flag; break;150}151}152153exec_ld((idb << 6) + dst);154155switch(dpl) {156case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC157case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC158case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR159}160161regs.dp ^= dphm << 4;162163if(rpdcr) regs.rp--;164}165166void NECDSP::exec_rt(uint24 opcode) {167exec_op(opcode);168regs.pc = regs.stack[--regs.sp];169}170171void NECDSP::exec_jp(uint24 opcode) {172uint9 brch = opcode >> 13; //branch173uint11 na = opcode >> 2; //next address174uint2 bank = opcode >> 0; //bank address175176uint14 jp = (regs.pc & 0x2000) | (bank << 11) | (na << 0);177178switch(brch) {179case 0x000: regs.pc = regs.so; return; //JMPSO180181case 0x080: if(regs.flaga.c == 0) regs.pc = jp; return; //JNCA182case 0x082: if(regs.flaga.c == 1) regs.pc = jp; return; //JCA183case 0x084: if(regs.flagb.c == 0) regs.pc = jp; return; //JNCB184case 0x086: if(regs.flagb.c == 1) regs.pc = jp; return; //JCB185186case 0x088: if(regs.flaga.z == 0) regs.pc = jp; return; //JNZA187case 0x08a: if(regs.flaga.z == 1) regs.pc = jp; return; //JZA188case 0x08c: if(regs.flagb.z == 0) regs.pc = jp; return; //JNZB189case 0x08e: if(regs.flagb.z == 1) regs.pc = jp; return; //JZB190191case 0x090: if(regs.flaga.ov0 == 0) regs.pc = jp; return; //JNOVA0192case 0x092: if(regs.flaga.ov0 == 1) regs.pc = jp; return; //JOVA0193case 0x094: if(regs.flagb.ov0 == 0) regs.pc = jp; return; //JNOVB0194case 0x096: if(regs.flagb.ov0 == 1) regs.pc = jp; return; //JOVB0195196case 0x098: if(regs.flaga.ov1 == 0) regs.pc = jp; return; //JNOVA1197case 0x09a: if(regs.flaga.ov1 == 1) regs.pc = jp; return; //JOVA1198case 0x09c: if(regs.flagb.ov1 == 0) regs.pc = jp; return; //JNOVB1199case 0x09e: if(regs.flagb.ov1 == 1) regs.pc = jp; return; //JOVB1200201case 0x0a0: if(regs.flaga.s0 == 0) regs.pc = jp; return; //JNSA0202case 0x0a2: if(regs.flaga.s0 == 1) regs.pc = jp; return; //JSA0203case 0x0a4: if(regs.flagb.s0 == 0) regs.pc = jp; return; //JNSB0204case 0x0a6: if(regs.flagb.s0 == 1) regs.pc = jp; return; //JSB0205206case 0x0a8: if(regs.flaga.s1 == 0) regs.pc = jp; return; //JNSA1207case 0x0aa: if(regs.flaga.s1 == 1) regs.pc = jp; return; //JSA1208case 0x0ac: if(regs.flagb.s1 == 0) regs.pc = jp; return; //JNSB1209case 0x0ae: if(regs.flagb.s1 == 1) regs.pc = jp; return; //JSB1210211case 0x0b0: if((regs.dp & 0x0f) == 0x00) regs.pc = jp; return; //JDPL0212case 0x0b1: if((regs.dp & 0x0f) != 0x00) regs.pc = jp; return; //JDPLN0213case 0x0b2: if((regs.dp & 0x0f) == 0x0f) regs.pc = jp; return; //JDPLF214case 0x0b3: if((regs.dp & 0x0f) != 0x0f) regs.pc = jp; return; //JDPLNF215216case 0x0bc: if(regs.sr.rqm == 0) regs.pc = jp; return; //JNRQM217case 0x0be: if(regs.sr.rqm == 1) regs.pc = jp; return; //JRQM218219case 0x100: regs.pc = jp & ~0x2000; return; //LJMP220case 0x101: regs.pc = jp | 0x2000; return; //HJMP221222case 0x140: regs.stack[regs.sp++] = regs.pc; regs.pc = jp & ~0x2000; return; //LCALL223case 0x141: regs.stack[regs.sp++] = regs.pc; regs.pc = jp | 0x2000; return; //HCALL224}225}226227void NECDSP::exec_ld(uint24 opcode) {228uint16 id = opcode >> 6; //immediate data229uint4 dst = opcode >> 0; //destination230231switch(dst) {232case 0: break;233case 1: regs.a = id; break;234case 2: regs.b = id; break;235case 3: regs.tr = id; break;236case 4: regs.dp = id; break;237case 5: regs.rp = id; break;238case 6: regs.dr = id; regs.sr.rqm = 1; break;239case 7: regs.sr = (regs.sr & 0x907c) | (id & ~0x907c); break;240case 8: regs.so = id; break; //LSB241case 9: regs.so = id; break; //MSB242case 10: regs.k = id; break;243case 11: regs.k = id; regs.l = dataROM[regs.rp]; break;244case 12: regs.l = id; regs.k = dataRAM[regs.dp | 0x40]; break;245case 13: regs.l = id; break;246case 14: regs.trb = id; break;247case 15: dataRAM[regs.dp] = id; break;248}249}250251void NECDSP::init() {252}253254void NECDSP::load() {255if(revision == Revision::uPD96050) {256cartridge.nvram.append({ "upd96050.ram", (uint8_t*)dataRAM, 4096 });257}258}259260void NECDSP::unload() {261}262263void NECDSP::power() {264if(revision == Revision::uPD7725) {265regs.pc.bits(11);266regs.rp.bits(10);267regs.dp.bits( 8);268}269270if(revision == Revision::uPD96050) {271regs.pc.bits(14);272regs.rp.bits(11);273regs.dp.bits(11);274}275}276277void NECDSP::reset() {278create(NECDSP::Enter, frequency);279280for(unsigned n = 0; n < 16; n++) regs.stack[n] = 0x0000;281regs.pc = 0x0000;282regs.rp = 0x0000;283regs.dp = 0x0000;284regs.sp = 0x0;285regs.k = 0x0000;286regs.l = 0x0000;287regs.m = 0x0000;288regs.n = 0x0000;289regs.a = 0x0000;290regs.b = 0x0000;291regs.flaga = 0x00;292regs.flagb = 0x00;293regs.tr = 0x0000;294regs.trb = 0x0000;295regs.sr = 0x0000;296regs.dr = 0x0000;297regs.si = 0x0000;298regs.so = 0x0000;299}300301NECDSP::NECDSP() {302}303304NECDSP::~NECDSP() {305}306307}308309310