Path: blob/master/libsnes/bsnes/snes/smp/core/opcodes.cpp
2 views
#ifdef SMPCORE_CPP1#define call (this->*op)23template<uint8 (SMPcore::*op)(uint8)>4void SMPcore::op_adjust(uint8 &r) {5op_io();6r = call(r);7}89template<uint8 (SMPcore::*op)(uint8)>10void SMPcore::op_adjust_addr() {11dp.l = op_readpc();12dp.h = op_readpc();13rd = op_read(dp);14rd = call(rd);15op_write(dp, rd);16}1718template<uint8 (SMPcore::*op)(uint8)>19void SMPcore::op_adjust_dp() {20dp = op_readpc();21rd = op_readdp(dp);22rd = call(rd);23op_writedp(dp, rd);24}2526void SMPcore::op_adjust_dpw(signed n) {27dp = op_readpc();28rd.w = op_readdp(dp) + n;29op_writedp(dp++, rd.l);30rd.h += op_readdp(dp);31op_writedp(dp++, rd.h);32regs.p.n = rd & 0x8000;33regs.p.z = rd == 0;34}3536template<uint8 (SMPcore::*op)(uint8)>37void SMPcore::op_adjust_dpx() {38dp = op_readpc();39op_io();40rd = op_readdp(dp + regs.x);41rd = call(rd);42op_writedp(dp + regs.x, rd);43}4445void SMPcore::op_branch(bool condition) {46rd = op_readpc();47if(condition == false) return;48op_io();49op_io();50regs.pc += (int8)rd;51}5253void SMPcore::op_branch_bit() {54dp = op_readpc();55sp = op_readdp(dp);56rd = op_readpc();57op_io();58if((bool)(sp & (1 << (opcode >> 5))) == (bool)(opcode & 0x10)) return;59op_io();60op_io();61regs.pc += (int8)rd;62}6364void SMPcore::op_pull(uint8 &r) {65op_io();66op_io();67r = op_readsp();68}6970void SMPcore::op_push(uint8 r) {71op_io();72op_io();73op_writesp(r);74}7576template<uint8 (SMPcore::*op)(uint8, uint8)>77void SMPcore::op_read_addr(uint8 &r) {78dp.l = op_readpc();79dp.h = op_readpc();80rd = op_read(dp);81r = call(r, rd);82}8384template<uint8 (SMPcore::*op)(uint8, uint8)>85void SMPcore::op_read_addri(uint8 &r) {86dp.l = op_readpc();87dp.h = op_readpc();88op_io();89rd = op_read(dp + r);90regs.a = call(regs.a, rd);91}9293template<uint8 (SMPcore::*op)(uint8, uint8)>94void SMPcore::op_read_const(uint8 &r) {95rd = op_readpc();96r = call(r, rd);97}9899template<uint8 (SMPcore::*op)(uint8, uint8)>100void SMPcore::op_read_dp(uint8 &r) {101dp = op_readpc();102rd = op_readdp(dp);103r = call(r, rd);104}105106template<uint8 (SMPcore::*op)(uint8, uint8)>107void SMPcore::op_read_dpi(uint8 &r, uint8 &i) {108dp = op_readpc();109op_io();110rd = op_readdp(dp + i);111r = call(r, rd);112}113114template<uint16 (SMPcore::*op)(uint16, uint16)>115void SMPcore::op_read_dpw() {116dp = op_readpc();117rd.l = op_readdp(dp++);118if(op != &SMPcore::op_cpw) op_io();119rd.h = op_readdp(dp++);120regs.ya = call(regs.ya, rd);121}122123template<uint8 (SMPcore::*op)(uint8, uint8)>124void SMPcore::op_read_idpx() {125dp = op_readpc() + regs.x;126op_io();127sp.l = op_readdp(dp++);128sp.h = op_readdp(dp++);129rd = op_read(sp);130regs.a = call(regs.a, rd);131}132133template<uint8 (SMPcore::*op)(uint8, uint8)>134void SMPcore::op_read_idpy() {135dp = op_readpc();136op_io();137sp.l = op_readdp(dp++);138sp.h = op_readdp(dp++);139rd = op_read(sp + regs.y);140regs.a = call(regs.a, rd);141}142143template<uint8 (SMPcore::*op)(uint8, uint8)>144void SMPcore::op_read_ix() {145op_io();146rd = op_readdp(regs.x);147regs.a = call(regs.a, rd);148}149150void SMPcore::op_set_addr_bit() {151dp.l = op_readpc();152dp.h = op_readpc();153bit = dp >> 13;154dp &= 0x1fff;155rd = op_read(dp);156switch(opcode >> 5) {157case 0: //orc addr:bit158case 1: //orc !addr:bit159op_io();160regs.p.c |= (rd & (1 << bit)) ^ (bool)(opcode & 0x20);161break;162case 2: //and addr:bit163case 3: //and !addr:bit164regs.p.c &= (rd & (1 << bit)) ^ (bool)(opcode & 0x20);165break;166case 4: //eor addr:bit167op_io();168regs.p.c ^= (bool)(rd & (1 << bit));169break;170case 5: //ldc addr:bit171regs.p.c = (rd & (1 << bit));172break;173case 6: //stc addr:bit174op_io();175rd = (rd & ~(1 << bit)) | (regs.p.c << bit);176op_write(dp, rd);177break;178case 7: //not addr:bit179rd ^= 1 << bit;180op_write(dp, rd);181break;182}183}184185void SMPcore::op_set_bit() {186dp = op_readpc();187rd = op_readdp(dp) & ~(1 << (opcode >> 5));188op_writedp(dp, rd | (!(opcode & 0x10) << (opcode >> 5)));189}190191void SMPcore::op_set_flag(bool &flag, bool data) {192op_io();193if(&flag == ®s.p.i) op_io();194flag = data;195}196197void SMPcore::op_test_addr(bool set) {198dp.l = op_readpc();199dp.h = op_readpc();200rd = op_read(dp);201regs.p.n = (regs.a - rd) & 0x80;202regs.p.z = (regs.a - rd) == 0;203op_read(dp);204op_write(dp, set ? rd | regs.a : rd & ~regs.a);205}206207void SMPcore::op_transfer(uint8 &from, uint8 &to) {208op_io();209to = from;210if(&to == ®s.s) return;211regs.p.n = (to & 0x80);212regs.p.z = (to == 0);213}214215void SMPcore::op_write_addr(uint8 &r) {216dp.l = op_readpc();217dp.h = op_readpc();218op_read(dp);219op_write(dp, r);220}221222void SMPcore::op_write_addri(uint8 &i) {223dp.l = op_readpc();224dp.h = op_readpc();225op_io();226dp += i;227op_read(dp);228op_write(dp, regs.a);229}230231void SMPcore::op_write_dp(uint8 &r) {232dp = op_readpc();233op_readdp(dp);234op_writedp(dp, r);235}236237void SMPcore::op_write_dpi(uint8 &r, uint8 &i) {238dp = op_readpc() + i;239op_io();240op_readdp(dp);241op_writedp(dp, r);242}243244template<uint8 (SMPcore::*op)(uint8, uint8)>245void SMPcore::op_write_dp_const() {246rd = op_readpc();247dp = op_readpc();248wr = op_readdp(dp);249wr = call(wr, rd);250op != &SMPcore::op_cmp ? op_writedp(dp, wr) : op_io();251}252253template<uint8 (SMPcore::*op)(uint8, uint8)>254void SMPcore::op_write_dp_dp() {255sp = op_readpc();256rd = op_readdp(sp);257dp = op_readpc();258if(op != &SMPcore::op_st) wr = op_readdp(dp);259wr = call(wr, rd);260op != &SMPcore::op_cmp ? op_writedp(dp, wr) : op_io();261}262263template<uint8 (SMPcore::*op)(uint8, uint8)>264void SMPcore::op_write_ix_iy() {265op_io();266rd = op_readdp(regs.y);267wr = op_readdp(regs.x);268wr = call(wr, rd);269op != &SMPcore::op_cmp ? op_writedp(regs.x, wr) : op_io();270}271272//273274void SMPcore::op_bne_dp() {275dp = op_readpc();276sp = op_readdp(dp);277rd = op_readpc();278op_io();279if(regs.a == sp) return;280op_io();281op_io();282regs.pc += (int8)rd;283}284285void SMPcore::op_bne_dpdec() {286dp = op_readpc();287wr = op_readdp(dp);288op_writedp(dp, --wr);289rd = op_readpc();290if(wr == 0) return;291op_io();292op_io();293regs.pc += (int8)rd;294}295296void SMPcore::op_bne_dpx() {297dp = op_readpc();298op_io();299sp = op_readdp(dp + regs.x);300rd = op_readpc();301op_io();302if(regs.a == sp) return;303op_io();304op_io();305regs.pc += (int8)rd;306}307308void SMPcore::op_bne_ydec() {309rd = op_readpc();310op_io();311op_io();312if(--regs.y == 0) return;313op_io();314op_io();315regs.pc += (int8)rd;316}317318void SMPcore::op_brk() {319rd.l = op_read(0xffde);320rd.h = op_read(0xffdf);321op_io();322op_io();323op_writesp(regs.pc.h);324op_writesp(regs.pc.l);325op_writesp(regs.p);326regs.pc = rd;327regs.p.b = 1;328regs.p.i = 0;329}330331void SMPcore::op_clv() {332op_io();333regs.p.v = 0;334regs.p.h = 0;335}336337void SMPcore::op_cmc() {338op_io();339op_io();340regs.p.c = !regs.p.c;341}342343void SMPcore::op_daa() {344op_io();345op_io();346if(regs.p.c || (regs.a) > 0x99) {347regs.a += 0x60;348regs.p.c = 1;349}350if(regs.p.h || (regs.a & 15) > 0x09) {351regs.a += 0x06;352}353regs.p.n = (regs.a & 0x80);354regs.p.z = (regs.a == 0);355}356357void SMPcore::op_das() {358op_io();359op_io();360if(!regs.p.c || (regs.a) > 0x99) {361regs.a -= 0x60;362regs.p.c = 0;363}364if(!regs.p.h || (regs.a & 15) > 0x09) {365regs.a -= 0x06;366}367regs.p.n = (regs.a & 0x80);368regs.p.z = (regs.a == 0);369}370371void SMPcore::op_div_ya_x() {372op_io();373op_io();374op_io();375op_io();376op_io();377op_io();378op_io();379op_io();380op_io();381op_io();382op_io();383ya = regs.ya;384//overflow set if quotient >= 256385regs.p.v = (regs.y >= regs.x);386regs.p.h = ((regs.y & 15) >= (regs.x & 15));387if(regs.y < (regs.x << 1)) {388//if quotient is <= 511 (will fit into 9-bit result)389regs.a = ya / regs.x;390regs.y = ya % regs.x;391} else {392//otherwise, the quotient won't fit into regs.p.v + regs.a393//this emulates the odd behavior of the S-SMP in this case394regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x);395regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x);396}397//result is set based on a (quotient) only398regs.p.n = (regs.a & 0x80);399regs.p.z = (regs.a == 0);400}401402void SMPcore::op_jmp_addr() {403rd.l = op_readpc();404rd.h = op_readpc();405regs.pc = rd;406}407408void SMPcore::op_jmp_iaddrx() {409dp.l = op_readpc();410dp.h = op_readpc();411op_io();412dp += regs.x;413rd.l = op_read(dp++);414rd.h = op_read(dp++);415regs.pc = rd;416}417418void SMPcore::op_jsp_dp() {419rd = op_readpc();420op_io();421op_io();422op_writesp(regs.pc.h);423op_writesp(regs.pc.l);424regs.pc = 0xff00 | rd;425}426427void SMPcore::op_jsr_addr() {428rd.l = op_readpc();429rd.h = op_readpc();430op_io();431op_io();432op_io();433op_writesp(regs.pc.h);434op_writesp(regs.pc.l);435regs.pc = rd;436}437438void SMPcore::op_jst() {439dp = 0xffde - ((opcode >> 4) << 1);440rd.l = op_read(dp++);441rd.h = op_read(dp++);442op_io();443op_io();444op_io();445op_writesp(regs.pc.h);446op_writesp(regs.pc.l);447regs.pc = rd;448}449450void SMPcore::op_lda_ixinc() {451op_io();452regs.a = op_readdp(regs.x++);453op_io();454regs.p.n = regs.a & 0x80;455regs.p.z = regs.a == 0;456}457458void SMPcore::op_mul_ya() {459op_io();460op_io();461op_io();462op_io();463op_io();464op_io();465op_io();466op_io();467ya = regs.y * regs.a;468regs.a = ya;469regs.y = ya >> 8;470//result is set based on y (high-byte) only471regs.p.n = (regs.y & 0x80);472regs.p.z = (regs.y == 0);473}474475void SMPcore::op_nop() {476op_io();477}478479void SMPcore::op_plp() {480op_io();481op_io();482regs.p = op_readsp();483}484485void SMPcore::op_rti() {486regs.p = op_readsp();487rd.l = op_readsp();488rd.h = op_readsp();489op_io();490op_io();491regs.pc = rd;492}493494void SMPcore::op_rts() {495rd.l = op_readsp();496rd.h = op_readsp();497op_io();498op_io();499regs.pc = rd;500}501502void SMPcore::op_sta_idpx() {503sp = op_readpc() + regs.x;504op_io();505dp.l = op_readdp(sp++);506dp.h = op_readdp(sp++);507op_read(dp);508op_write(dp, regs.a);509}510511void SMPcore::op_sta_idpy() {512sp = op_readpc();513dp.l = op_readdp(sp++);514dp.h = op_readdp(sp++);515op_io();516dp += regs.y;517op_read(dp);518op_write(dp, regs.a);519}520521void SMPcore::op_sta_ix() {522op_io();523op_readdp(regs.x);524op_writedp(regs.x, regs.a);525}526527void SMPcore::op_sta_ixinc() {528op_io();529op_io();530op_writedp(regs.x++, regs.a);531}532533void SMPcore::op_stw_dp() {534dp = op_readpc();535op_readdp(dp);536op_writedp(dp++, regs.a);537op_writedp(dp++, regs.y);538}539540void SMPcore::op_wait() {541while(true) {542if(scheduler.sync == Scheduler::SynchronizeMode::All) {543regs.pc--; // repeat this opcode on next run544scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);545}546op_io();547op_io();548}549}550551void SMPcore::op_xcn() {552op_io();553op_io();554op_io();555op_io();556regs.a = (regs.a >> 4) | (regs.a << 4);557regs.p.n = regs.a & 0x80;558regs.p.z = regs.a == 0;559}560561#undef call562#endif563564565