📄 cpu.c
字号:
/* * Softcam plugin to VDR (C++) * * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "data.h"#include "cpu.h"#include "log-nagra.h"#define LOGLBPUT(...) loglb->Printf(__VA_ARGS__)#define CCLOGLBPUT(...) do { if(doDisAsm) loglb->Printf(__VA_ARGS__); } while(0)// -- cMapMem ------------------------------------------------------------------cMapMem::cMapMem(unsigned short Offset, int Size){ offset=Offset; size=Size; if((mem=(unsigned char *)malloc(size))) memset(mem,0,size);// PRINTF(L_SYS_EMU,"mapmem: new map off=%04x size=%04x",offset,size);}cMapMem::~cMapMem(){ free(mem);}bool cMapMem::IsFine(void){ return (mem!=0);}unsigned char cMapMem::Get(unsigned short ea){ return (ea>=offset && ea<offset+size) ? mem[ea-offset] : 0;}void cMapMem::Set(unsigned short ea, unsigned char val){ if(ea>=offset && ea<offset+size) mem[ea-offset]=val;}// -- cMapRom ------------------------------------------------------------------cMapRom::cMapRom(unsigned short Offset, const char *Filename, int InFileOffset){ offset=Offset; addr=0; fm=filemaps.GetFileMap(Filename,FILEMAP_DOMAIN,false); if(fm && fm->Map()) { addr=fm->Addr()+InFileOffset; size=fm->Size()-InFileOffset; PRINTF(L_SYS_EMU,"maprom: new map off=%04x size=%04x",offset,size); }}cMapRom::~cMapRom(){ if(fm) fm->Unmap();}bool cMapRom::IsFine(void){ return addr!=0 && size>0;}unsigned char cMapRom::Get(unsigned short ea){ return (ea>=offset && ea<offset+size) ? addr[ea-offset] : 0;}void cMapRom::Set(unsigned short ea, unsigned char val){ if(ea>=offset && ea<offset+size) LOGLBPUT("[ROM] "); // this is a ROM!}// -- cMapEeprom ---------------------------------------------------------------cMapEeprom::cMapEeprom(unsigned short Offset, const char *Filename, int OtpSize, int InFileOffset){ offset=Offset; otpSize=OtpSize; addr=0; fm=filemaps.GetFileMap(Filename,FILEMAP_DOMAIN,true); if(fm && fm->Map()) { addr=fm->Addr()+InFileOffset; size=fm->Size()-InFileOffset; PRINTF(L_SYS_EMU,"mapeeprom: new map off=%04x size=%04x otp=%04x",offset,size,otpSize); }}cMapEeprom::~cMapEeprom(){ if(fm) fm->Unmap();}bool cMapEeprom::IsFine(void){ return (addr!=0);}unsigned char cMapEeprom::Get(unsigned short ea){ return (ea>=offset && ea<offset+size) ? addr[ea-offset] : 0;}void cMapEeprom::Set(unsigned short ea, unsigned char val){ if(ea>=offset && ea<offset+otpSize) { if(addr[ea-offset]==0) { addr[ea-offset]=val; LOGLBPUT("[OTP-SET] "); } LOGLBPUT("[OTP] "); } if(ea>=offset+otpSize && ea<offset+size) { addr[ea-offset]=val; LOGLBPUT("[EEP] "); }}// -- c6805 --------------------------------------------------------------------#define PAGEOFF(ea,s) (((ea)&0x8000) ? pageMap[s]:0)c6805::c6805(void) { cc.c=0; cc.z=0; cc.n=0; cc.i=0; cc.h=0; cc.v=1; pc=0; a=0; x=0; y=0; cr=dr=0; sp=spHi=0x100; spLow=0xC0; hasReadHandler=hasWriteHandler=false; exptBase=0x4000; ClearExceptions(); ClearBreakpoints(); InitMapper(); ResetCycles(); memset(stats,0,sizeof(stats)); loglb=new cLineBuff(128);}c6805::~c6805(){ if(LOG(L_SYS_CPUSTATS)) { int i, j, sort[256]; for(i=0; i<256; i++) sort[i]=i; for(i=0; i<256; i++) for(j=0; j<255; j++) if(stats[sort[j]]<stats[sort[j+1]]) { int x=sort[j]; sort[j]=sort[j+1]; sort[j+1]=x; } PRINTF(L_SYS_CPUSTATS,"opcode statistics"); for(i=0; i<256; i++) if((j=stats[sort[i]])) PRINTF(L_SYS_CPUSTATS,"opcode %02x: %d",sort[i],j); } ClearMapper(); delete loglb;}bool c6805::AddMapper(cMap *map, unsigned short start, int size, unsigned char seg){ if(map && map->IsFine()) { if(nextMapper<MAX_MAPPER) { map->loglb=loglb; mapper[nextMapper]=map; memset(&mapMap[start+PAGEOFF(start,seg)],nextMapper,size); nextMapper++; return true; } else PRINTF(L_SYS_EMU,"6805: too many mappers"); } else PRINTF(L_SYS_EMU,"6805: mapper not ready (start=%02x:%04x size=%04x)",seg,start,size); delete map; return false;}void c6805::ResetMapper(void){ ClearMapper(); InitMapper();}void c6805::InitMapper(void){ memset(mapMap,0,sizeof(mapMap)); memset(mapper,0,sizeof(mapper)); mapper[0]=new cMapMem(0,PAGE_SIZE*2); nextMapper=1; memset(pageMap,0,sizeof(pageMap)); pageMap[0]=PAGE_SIZE*0; pageMap[1]=PAGE_SIZE*1; pageMap[2]=PAGE_SIZE*2; pageMap[0x80]=PAGE_SIZE*3; pageMap[0x40]=PAGE_SIZE*4;}void c6805::ClearMapper(void){ for(int i=0; i<MAX_MAPPER; i++) delete mapper[i];}unsigned char c6805::Get(unsigned short ea) const{ return mapper[mapMap[ea+PAGEOFF(ea,cr)]&0x7f]->Get(ea);}unsigned char c6805::Get(unsigned char seg, unsigned short ea) const{ return mapper[mapMap[ea+PAGEOFF(ea,seg)]&0x7f]->Get(ea);}void c6805::Set(unsigned short ea, unsigned char val){ if(hasWriteHandler) WriteHandler(cr,ea,val); unsigned char mapId=mapMap[ea+PAGEOFF(ea,cr)]; if(!(mapId&0x80)) mapper[mapId&0x7f]->Set(ea,val);}void c6805::Set(unsigned char seg, unsigned short ea, unsigned char val){ if(hasWriteHandler) WriteHandler(seg,ea,val); unsigned char mapId=mapMap[ea+PAGEOFF(ea,seg)]; if(!(mapId&0x80)) mapper[mapId&0x7f]->Set(ea,val);}void c6805::ForceSet(unsigned short ea, unsigned char val, bool ro){ mapMap[ea]=0; // reset to RAM map Set(0,ea,val); // set value if(ro) mapMap[ea]|=0x80; // protect byte}void c6805::SetMem(unsigned short addr, const unsigned char *data, int len, unsigned char seg){ while(len>0) { Set(seg,addr++,*data++); len--; }}void c6805::GetMem(unsigned short addr, unsigned char *data, int len, unsigned char seg) const{ while(len>0) { *data++=Get(seg,addr++); len--; }}void c6805::SetSp(unsigned short SpHi, unsigned short SpLow){ spHi =sp=SpHi; spLow =SpLow;}void c6805::SetPc(unsigned short addr, unsigned char seg){ pc=addr; cr=seg; ResetCycles(); ClearExceptions();}void c6805::PopPc(void){ poppc();}void c6805::PopCr(void){ cr=pop();}void c6805::Push(unsigned char c){ push(c);}void c6805::AddBreakpoint(unsigned short addr){ if(numBp<MAX_BREAKPOINTS) { bp[numBp++]=addr; PRINTF(L_SYS_EMU,"6805: setting breakpoint at 0x%04x",addr); } else PRINTF(L_SYS_EMU,"6805: too many breakpoints");}void c6805::ClearBreakpoints(void){ numBp=0; memset(bp,0,sizeof(bp));}void c6805::AddCycles(unsigned int num){ if(num>0) { clockcycles+=num; if(timerDisable>0) { timerDisable-=num; if(timerDisable<0) timerDisable=0; } if(!timerDisable) TimerHandler(num); }}void c6805::ResetCycles(void){ clockcycles=0;}void c6805::RaiseException(int num){ if(num<EXPT_MAX) { exptPending=true; expt[num]=true; }}void c6805::ClearExceptions(void){ exptPending=false; timerDisable=0; for(int i=0; i<EXPT_MAX; i++) expt[i]=false;}void c6805::DisableTimers(int num){ timerDisable=num;}void c6805::SetExptBase(unsigned short base){ exptBase=base;}static const char * const ops[] = {// 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f/* 0x00 */ "BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR",/* 0x10 */ "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR",/* 0x20 */ "BRA", "BRN", "BHI", "BLS", "BCC", "BCS", "BNE", "BEQ", "BHCC", "BHCS", "BPL", "BMI", "BMC", "BMS", "BIL", "BIH",/* 0x30 */ "NEG", "pre31","pre32","COM", "LSR", "op35", "ROR", "ASR", "ASL", "ROL", "DEC", "op3b", "INC", "TST", "SWAP", "CLR",/* 0x40 */ "NEG", "op41", "MUL", "COM", "LSR", "op45", "ROR", "ASR", "ASL", "ROL", "DEC", "op4b", "INC", "TST", "SWAP", "CLR",/* 0x50 */ "NEG", "op51", "MUL", "COM", "LSR", "op55", "ROR", "ASR", "ASL", "ROL", "DEC", "op5b", "INC", "TST", "SWAP", "CLR",/* 0x60 */ "NEG", "op61", "op62", "COM", "LSR", "op65", "ROR", "ASR", "ASL", "ROL", "DEC", "op6b", "INC", "TST", "SWAP", "CLR",/* 0x70 */ "NEG", "LDD", "LDD", "COM", "LSR", "LDD", "ROR", "ASR", "ASL", "ROL", "DEC", "TAD", "INC", "TST", "SWAP", "CLR",/* 0x80 */ "RTI", "RTS", "op82", "SWI", "POPA", "POP%c","POPC", "PRTS", "PUSHA","PUSH%c","PUSHC","TDA", "TCA", "PJSR", "STOP", "WAIT",/* 0x90 */ "pre90","pre91","pre92","T%2$c%1$c","T%cS","TAS","TS%c","TA%c", "CLC", "SEC", "CLI", "SEI", "RSP", "NOP", "TSA", "T%cA",/* 0xa0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "opa7", "EOR", "ADC", "ORA", "ADD", "PUSHD","BSR", "LD%c", "POPD",/* 0xb0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "STA", "EOR", "ADC", "ORA", "ADD", "JMP", "JSR", "LD%c", "ST%c",/* 0xc0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "STA", "EOR", "ADC", "ORA", "ADD", "JMP", "JSR", "LD%c", "ST%c",/* 0xd0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "STA", "EOR", "ADC", "ORA", "ADD", "JMP", "JSR", "LD%c", "ST%c",/* 0xe0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "STA", "EOR", "ADC", "ORA", "ADD", "JMP", "JSR", "LD%c", "ST%c",/* 0xf0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "STA", "EOR", "ADC", "ORA", "ADD", "JMP", "JSR", "LD%c", "ST%c", };static const char * const vops[] = { "BVGT","BVLE","BVGE","BVLT","BVC","BVS" };// Flags:// 1 - read operant// 2 - write operant// 4 - use dr register// 8 - special address mode in high nibblestatic const char opFlags[] = {// 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f/* 0x00 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,/* 0x10 */ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,/* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/* 0x30 */ 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02,/* 0x40 */ 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02,/* 0x50 */ 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02,/* 0x60 */ 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02,/* 0x70 */ 0x03, 0xA9, 0xB9, 0x03, 0x03, 0xC9, 0x03, 0x03, 0x03, 0x03, 0x03, 0x88, 0x03, 0x01, 0x03, 0x02,/* 0x80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/* 0x90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/* 0xa0 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x88, 0x88, 0x01, 0x88,/* 0xb0 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02,/* 0xc0 */ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x05, 0x06,/* 0xd0 */ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x05, 0x06,/* 0xe0 */ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x05, 0x06,/* 0xf0 */ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x05, 0x06, };static const unsigned char clock_cycles[] = {// 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f/* 0x00 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,/* 0x10 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,/* 0x20 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,/* 0x30 */ 5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 4, 5, 5,/* 0x40 */ 3, 0, 11, 3, 3, 0, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3,/* 0x50 */ 3, 0, 0, 3, 3, 0, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -