|
SASC
DVBSoftCAM
|
00001 /* 00002 * Softcam plugin to VDR (C++) 00003 * 00004 * This code is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This code is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html 00018 */ 00019 00020 #include <stdio.h> 00021 #include <stdlib.h> 00022 #include <string.h> 00023 00024 #include "data.h" 00025 #include "cpu.h" 00026 #include "log-nagra.h" 00027 00028 #define LOGLBPUT(...) loglb->Printf(__VA_ARGS__) 00029 #define CCLOGLBPUT(...) do { if(doDisAsm) loglb->Printf(__VA_ARGS__); } while(0) 00030 00031 // -- cMapMem ------------------------------------------------------------------ 00032 00033 cMapMem::cMapMem(unsigned short Offset, int Size) 00034 { 00035 offset=Offset; size=Size; 00036 if((mem=(unsigned char *)malloc(size))) 00037 memset(mem,0,size); 00038 // PRINTF(L_SYS_EMU,"mapmem: new map off=%04x size=%04x",offset,size); 00039 } 00040 00041 cMapMem::~cMapMem() 00042 { 00043 free(mem); 00044 } 00045 00046 bool cMapMem::IsFine(void) 00047 { 00048 return (mem!=0); 00049 } 00050 00051 unsigned char cMapMem::Get(unsigned short ea) 00052 { 00053 return (ea>=offset && ea<offset+size) ? mem[ea-offset] : 0; 00054 } 00055 00056 void cMapMem::Set(unsigned short ea, unsigned char val) 00057 { 00058 if(ea>=offset && ea<offset+size) 00059 mem[ea-offset]=val; 00060 } 00061 00062 // -- cMapRom ------------------------------------------------------------------ 00063 00064 cMapRom::cMapRom(unsigned short Offset, const char *Filename, int InFileOffset) 00065 { 00066 offset=Offset; addr=0; 00067 fm=filemaps.GetFileMap(Filename,FILEMAP_DOMAIN,false); 00068 if(fm && fm->Map()) { 00069 addr=fm->Addr()+InFileOffset; 00070 size=fm->Size()-InFileOffset; 00071 PRINTF(L_SYS_EMU,"maprom: new map off=%04x size=%04x",offset,size); 00072 } 00073 } 00074 00075 cMapRom::~cMapRom() 00076 { 00077 if(fm) fm->Unmap(); 00078 } 00079 00080 bool cMapRom::IsFine(void) 00081 { 00082 return addr!=0 && size>0; 00083 } 00084 00085 unsigned char cMapRom::Get(unsigned short ea) 00086 { 00087 return (ea>=offset && ea<offset+size) ? addr[ea-offset] : 0; 00088 } 00089 00090 void cMapRom::Set(unsigned short ea, unsigned char val) 00091 { 00092 if(ea>=offset && ea<offset+size) LOGLBPUT("[ROM] "); 00093 // this is a ROM! 00094 } 00095 00096 // -- cMapEeprom --------------------------------------------------------------- 00097 00098 cMapEeprom::cMapEeprom(unsigned short Offset, const char *Filename, int OtpSize, int InFileOffset) 00099 { 00100 offset=Offset; otpSize=OtpSize; addr=0; 00101 fm=filemaps.GetFileMap(Filename,FILEMAP_DOMAIN,true); 00102 if(fm && fm->Map()) { 00103 addr=fm->Addr()+InFileOffset; 00104 size=fm->Size()-InFileOffset; 00105 PRINTF(L_SYS_EMU,"mapeeprom: new map off=%04x size=%04x otp=%04x",offset,size,otpSize); 00106 } 00107 } 00108 00109 cMapEeprom::~cMapEeprom() 00110 { 00111 if(fm) fm->Unmap(); 00112 } 00113 00114 bool cMapEeprom::IsFine(void) 00115 { 00116 return (addr!=0); 00117 } 00118 00119 unsigned char cMapEeprom::Get(unsigned short ea) 00120 { 00121 return (ea>=offset && ea<offset+size) ? addr[ea-offset] : 0; 00122 } 00123 00124 void cMapEeprom::Set(unsigned short ea, unsigned char val) 00125 { 00126 if(ea>=offset && ea<offset+otpSize) { 00127 if(addr[ea-offset]==0) { 00128 addr[ea-offset]=val; 00129 LOGLBPUT("[OTP-SET] "); 00130 } 00131 LOGLBPUT("[OTP] "); 00132 } 00133 if(ea>=offset+otpSize && ea<offset+size) { 00134 addr[ea-offset]=val; 00135 LOGLBPUT("[EEP] "); 00136 } 00137 } 00138 00139 // -- c6805 -------------------------------------------------------------------- 00140 00141 #define PAGEOFF(ea,s) (((ea)&0x8000) ? pageMap[s]:0) 00142 00143 c6805::c6805(void) 00144 { 00145 cc.c=0; cc.z=0; cc.n=0; cc.i=0; cc.h=0; cc.v=1; 00146 pc=0; a=0; x=0; y=0; cr=dr=0; sp=spHi=0x100; spLow=0xC0; 00147 hasReadHandler=hasWriteHandler=false; 00148 exptBase=0x4000; 00149 ResetCycles(); 00150 ClearExceptions(); 00151 ClearBreakpoints(); 00152 InitMapper(); 00153 memset(stats,0,sizeof(stats)); 00154 loglb=new cLineBuff(128); 00155 } 00156 00157 c6805::~c6805() 00158 { 00159 if(LOG(L_SYS_CPUSTATS)) { 00160 int i, j, sort[256]; 00161 for(i=0; i<256; i++) sort[i]=i; 00162 for(i=0; i<256; i++) 00163 for(j=0; j<255; j++) 00164 if(stats[sort[j]]<stats[sort[j+1]]) { 00165 int x=sort[j]; sort[j]=sort[j+1]; sort[j+1]=x; 00166 } 00167 PRINTF(L_SYS_CPUSTATS,"opcode statistics"); 00168 for(i=0; i<256; i++) 00169 if((j=stats[sort[i]])) PRINTF(L_SYS_CPUSTATS,"opcode %02x: %d",sort[i],j); 00170 } 00171 ClearMapper(); 00172 delete loglb; 00173 } 00174 00175 bool c6805::AddMapper(cMap *map, unsigned short start, int size, unsigned char seg) 00176 { 00177 if(map && map->IsFine()) { 00178 if(nextMapper<MAX_MAPPER) { 00179 map->loglb=loglb; 00180 mapper[nextMapper]=map; 00181 memset(&mapMap[start+PAGEOFF(start,seg)],nextMapper,size); 00182 nextMapper++; 00183 return true; 00184 } 00185 else PRINTF(L_SYS_EMU,"6805: too many mappers"); 00186 } 00187 else PRINTF(L_SYS_EMU,"6805: mapper not ready (start=%02x:%04x size=%04x)",seg,start,size); 00188 delete map; 00189 return false; 00190 } 00191 00192 void c6805::ResetMapper(void) 00193 { 00194 ClearMapper(); InitMapper(); 00195 } 00196 00197 void c6805::InitMapper(void) 00198 { 00199 memset(mapMap,0,sizeof(mapMap)); 00200 memset(mapper,0,sizeof(mapper)); 00201 mapper[0]=new cMapMem(0,PAGE_SIZE*2); 00202 nextMapper=1; 00203 memset(pageMap,0,sizeof(pageMap)); 00204 pageMap[0]=PAGE_SIZE*0; 00205 pageMap[1]=PAGE_SIZE*1; 00206 pageMap[2]=PAGE_SIZE*2; 00207 pageMap[0x80]=PAGE_SIZE*3; 00208 pageMap[0x40]=PAGE_SIZE*4; 00209 } 00210 00211 void c6805::ClearMapper(void) 00212 { 00213 for(int i=0; i<MAX_MAPPER; i++) delete mapper[i]; 00214 } 00215 00216 unsigned char c6805::Get(unsigned short ea) const 00217 { 00218 return mapper[mapMap[ea+PAGEOFF(ea,cr)]&0x7f]->Get(ea); 00219 } 00220 00221 unsigned char c6805::Get(unsigned char seg, unsigned short ea) const 00222 { 00223 return mapper[mapMap[ea+PAGEOFF(ea,seg)]&0x7f]->Get(ea); 00224 } 00225 00226 void c6805::Set(unsigned short ea, unsigned char val) 00227 { 00228 if(hasWriteHandler) WriteHandler(cr,ea,val); 00229 unsigned char mapId=mapMap[ea+PAGEOFF(ea,cr)]; 00230 if(!(mapId&0x80)) mapper[mapId&0x7f]->Set(ea,val); 00231 } 00232 00233 void c6805::Set(unsigned char seg, unsigned short ea, unsigned char val) 00234 { 00235 if(hasWriteHandler) WriteHandler(seg,ea,val); 00236 unsigned char mapId=mapMap[ea+PAGEOFF(ea,seg)]; 00237 if(!(mapId&0x80)) mapper[mapId&0x7f]->Set(ea,val); 00238 } 00239 00240 void c6805::ForceSet(unsigned short ea, unsigned char val, bool ro) 00241 { 00242 mapMap[ea]=0; // reset to RAM map 00243 Set(0,ea,val); // set value 00244 if(ro) mapMap[ea]|=0x80; // protect byte 00245 } 00246 00247 void c6805::SetMem(unsigned short addr, const unsigned char *data, int len, unsigned char seg) 00248 { 00249 while(len>0) { Set(seg,addr++,*data++); len--; } 00250 } 00251 00252 void c6805::GetMem(unsigned short addr, unsigned char *data, int len, unsigned char seg) const 00253 { 00254 while(len>0) { *data++=Get(seg,addr++); len--; } 00255 } 00256 00257 void c6805::SetSp(unsigned short SpHi, unsigned short SpLow) 00258 { 00259 spHi =sp=SpHi; 00260 spLow =SpLow; 00261 } 00262 00263 void c6805::SetPc(unsigned short addr, unsigned char seg) 00264 { 00265 pc=addr; cr=seg; 00266 ResetCycles(); 00267 ClearExceptions(); 00268 } 00269 00270 void c6805::PopPc(void) 00271 { 00272 poppc(); 00273 } 00274 00275 void c6805::PopCr(void) 00276 { 00277 cr=pop(); 00278 } 00279 00280 void c6805::Push(unsigned char c) 00281 { 00282 push(c); 00283 } 00284 00285 void c6805::AddBreakpoint(unsigned short addr) 00286 { 00287 if(numBp<MAX_BREAKPOINTS) { 00288 bp[numBp++]=addr; 00289 PRINTF(L_SYS_EMU,"6805: setting breakpoint at 0x%04x",addr); 00290 } 00291 else PRINTF(L_SYS_EMU,"6805: too many breakpoints"); 00292 } 00293 00294 void c6805::ClearBreakpoints(void) 00295 { 00296 numBp=0; 00297 memset(bp,0,sizeof(bp)); 00298 } 00299 00300 void c6805::AddCycles(unsigned int num) 00301 { 00302 if(num>0) { 00303 clockcycles+=num; 00304 if(timerDisable>0) { 00305 timerDisable-=num; 00306 if(timerDisable<0) timerDisable=0; 00307 } 00308 if(!timerDisable) 00309 TimerHandler(num); 00310 } 00311 } 00312 00313 void c6805::ResetCycles(void) 00314 { 00315 clockcycles=0; 00316 } 00317 00318 void c6805::RaiseException(int num) 00319 { 00320 if(num<EXPT_MAX) { 00321 exptPending=true; 00322 expt[num]=true; 00323 } 00324 } 00325 00326 void c6805::ClearExceptions(void) 00327 { 00328 exptPending=false; exptReady=true; timerDisable=0; 00329 for(int i=0; i<EXPT_MAX; i++) expt[i]=false; 00330 } 00331 00332 void c6805::DisableTimers(int num) 00333 { 00334 timerDisable=num; 00335 } 00336 00337 void c6805::SetExptBase(unsigned short base) 00338 { 00339 exptBase=base; 00340 } 00341 00342 static const char * const ops[] = { 00343 // 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 00344 /* 0x00 */ "BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR", 00345 /* 0x10 */ "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", "BSET", "BCLR", 00346 /* 0x20 */ "BRA", "BRN", "BHI", "BLS", "BCC", "BCS", "BNE", "BEQ", "BHCC", "BHCS", "BPL", "BMI", "BMC", "BMS", "BIL", "BIH", 00347 /* 0x30 */ "NEG", "pre31","pre32","COM", "LSR", "op35", "ROR", "ASR", "ASL", "ROL", "DEC", "op3b", "INC", "TST", "SWAP", "CLR", 00348 /* 0x40 */ "NEG", "op41", "MUL", "COM", "LSR", "op45", "ROR", "ASR", "ASL", "ROL", "DEC", "op4b", "INC", "TST", "SWAP", "CLR", 00349 /* 0x50 */ "NEG", "op51", "MUL", "COM", "LSR", "op55", "ROR", "ASR", "ASL", "ROL", "DEC", "op5b", "INC", "TST", "SWAP", "CLR", 00350 /* 0x60 */ "NEG", "op61", "op62", "COM", "LSR", "op65", "ROR", "ASR", "ASL", "ROL", "DEC", "op6b", "INC", "TST", "SWAP", "CLR", 00351 /* 0x70 */ "NEG", "LDD", "LDD", "COM", "LSR", "LDD", "ROR", "ASR", "ASL", "ROL", "DEC", "TAD", "INC", "TST", "SWAP", "CLR", 00352 /* 0x80 */ "RTI", "RTS", "op82", "SWI", "POPA", "POP%c","POPC", "PRTS", "PUSHA","PUSH%c","PUSHC","TDA", "TCA", "PJSR", "STOP", "WAIT", 00353 /* 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", 00354 /* 0xa0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "opa7", "EOR", "ADC", "ORA", "ADD", "PUSHD","BSR", "LD%c", "POPD", 00355 /* 0xb0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "STA", "EOR", "ADC", "ORA", "ADD", "JMP", "JSR", "LD%c", "ST%c", 00356 /* 0xc0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "STA", "EOR", "ADC", "ORA", "ADD", "JMP", "JSR", "LD%c", "ST%c", 00357 /* 0xd0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "STA", "EOR", "ADC", "ORA", "ADD", "JMP", "JSR", "LD%c", "ST%c", 00358 /* 0xe0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "STA", "EOR", "ADC", "ORA", "ADD", "JMP", "JSR", "LD%c", "ST%c", 00359 /* 0xf0 */ "SUB", "CMP", "SBC", "CP%c", "AND", "BIT", "LDA", "STA", "EOR", "ADC", "ORA", "ADD", "JMP", "JSR", "LD%c", "ST%c", 00360 }; 00361 static const char * const vops[] = { 00362 "BVGT","BVLE","BVGE","BVLT","BVC","BVS" 00363 }; 00364 00365 // Flags: 00366 // 1 - read operant 00367 // 2 - write operant 00368 // 4 - use dr register 00369 // 8 - special address mode in high nibble 00370 static const char opFlags[] = { 00371 // 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 00372 /* 0x00 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 00373 /* 0x10 */ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 00374 /* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00375 /* 0x30 */ 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 00376 /* 0x40 */ 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 00377 /* 0x50 */ 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 00378 /* 0x60 */ 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 00379 /* 0x70 */ 0x03, 0xA9, 0xB9, 0x03, 0x03, 0xC9, 0x03, 0x03, 0x03, 0x03, 0x03, 0x88, 0x03, 0x01, 0x03, 0x02, 00380 /* 0x80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00381 /* 0x90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00382 /* 0xa0 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x88, 0x88, 0x01, 0x88, 00383 /* 0xb0 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 00384 /* 0xc0 */ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x05, 0x06, 00385 /* 0xd0 */ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x05, 0x06, 00386 /* 0xe0 */ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x05, 0x06, 00387 /* 0xf0 */ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x05, 0x06, 00388 }; 00389 00390 static const unsigned char clock_cycles[] = { 00391 // 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 00392 /* 0x00 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 00393 /* 0x10 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 00394 /* 0x20 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 00395 /* 0x30 */ 5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 4, 5, 5, 00396 /* 0x40 */ 3, 0, 11, 3, 3, 0, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 00397 /* 0x50 */ 3, 0, 0, 3, 3, 0, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 00398 /* 0x60 */ 6, 0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 0, 6, 5, 6, 6, 00399 /* 0x70 */ 5, 2, 3, 5, 5, 4, 5, 5, 5, 5, 5, 2, 5, 4, 5, 5, 00400 /* 0x80 */ 9, 6, 0, 10, 4, 4, 4, 6, 3, 3, 3, 2, 2, 7, 2, 2, 00401 /* 0x90 */ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 00402 /* 0xa0 */ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 3, 6, 2, 4, 00403 /* 0xb0 */ 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 2, 5, 3, 4, 00404 /* 0xc0 */ 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 3, 6, 4, 5, 00405 /* 0xd0 */ 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 4, 7, 5, 6, 00406 /* 0xe0 */ 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 3, 6, 4, 5, 00407 /* 0xf0 */ 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 2, 5, 3, 4, 00408 }; 00409 00410 char * c6805::PADDR(unsigned char s, unsigned short ea) 00411 { 00412 snprintf(addrBuff,sizeof(addrBuff),((ea&0x8000) && s>0)?"%2$x:%1$04x":"%04x",ea,s); 00413 return addrBuff; 00414 } 00415 00416 int c6805::Run(int max_count) 00417 { 00418 // returns: 00419 // 0 - breakpoint 00420 // 1 - stack overflow 00421 // 2 - instruction counter exeeded 00422 // 3 - unsupported instruction 00423 00424 bool disAsmHeader=false; 00425 disAsmLogClass=L_SYS_DISASM; 00426 if(LOG(L_SYS_DISASM)) doDisAsm=true; 00427 else { 00428 doDisAsm=false; 00429 if(LOG(L_SYS_DISASM80)) disAsmLogClass=L_SYS_DISASM80; 00430 } 00431 00432 int count=0; 00433 while (1) { 00434 if(exptPending && exptReady) { 00435 exptPending=false; 00436 for(int i=0; i<EXPT_MAX; ++i) 00437 if(expt[i]) { 00438 exptPending=true; // to force check for another interrupt in next Run pass 00439 expt[i]=false; 00440 pushpc(); push(x); push(a); pushc(); cc.i=1; 00441 pc=exptBase+4*i; 00442 timerDisable=0; 00443 break; 00444 } 00445 } 00446 exptReady=!cc.i; 00447 Stepper(); 00448 if(sp<spLow) { 00449 PRINTF(L_SYS_EMU,"stack overflow (count=%d)",count); 00450 return 1; 00451 } 00452 if(spHi>spLow && sp>spHi) { 00453 PRINTF(L_SYS_EMU,"stack underflow (count=%d)",count); 00454 return 1; 00455 } 00456 if(pc>0x0400 && mapMap[pc+PAGEOFF(pc,cr)]==0) { 00457 PRINTF(L_SYS_EMU,"NX protection at %04x (count=%d)",pc,count); 00458 return 1; 00459 } 00460 count++; 00461 00462 if(!LOG(L_SYS_DISASM) && LOG(L_SYS_DISASM80)) { 00463 bool flag=(pc>=0x80 && pc<0x200); 00464 if(doDisAsm && !flag) PRINTF(disAsmLogClass,"[...]"); 00465 doDisAsm=flag; 00466 } 00467 00468 if(doDisAsm && !disAsmHeader) { 00469 PRINTF(disAsmLogClass,"cr:-pc- aa xx yy dr -sp- VHINZC -mem@pc- -mem@sp- -cycles-"); 00470 disAsmHeader=true; 00471 } 00472 CCLOGLBPUT("%02x:%04x %02x %02x %02x %02x %04x %c%c%c%c%c%c %02x%02x%02x%02x %02x%02x%02x%02x %08x ", 00473 cr,pc,a,x,y,dr,sp, 00474 cc.v?'V':'.',cc.h?'H':'.',cc.i?'I':'.',cc.n?'N':'.',cc.z?'Z':'.',cc.c?'C':'.', 00475 Get(pc),Get(pc+1),Get(pc+2),Get(pc+3),Get(sp+1),Get(sp+2),Get(sp+3),Get(sp+4), 00476 clockcycles); 00477 00478 unsigned char *ex=&x; 00479 unsigned short idx=*ex; 00480 indirect=false; 00481 bool paged=false, vbra=false; 00482 unsigned char ins=Get(pc++); 00483 char xs='X', xi='X'; 00484 int cycles=0; 00485 00486 // check pre-bytes 00487 switch(ins) { 00488 case 0x31: // use SP indexed or indirect paged mode (ST19) 00489 cycles+=2; 00490 ins=Get(pc++); 00491 switch(ins) { 00492 case 0x22: case 0x23: case 0x24: case 0x25: 00493 case 0x26: case 0x27: 00494 vbra=true; break; 00495 case 0x8D: 00496 cycles++; 00497 // fall through 00498 case 0x75: 00499 case 0xC0: case 0xC1: case 0xC2: case 0xC3: 00500 case 0xC4: case 0xC5: case 0xC6: case 0xC7: 00501 case 0xC8: case 0xC9: case 0xCA: case 0xCB: 00502 case 0xCE: case 0xCF: 00503 case 0xD0: case 0xD1: case 0xD2: case 0xD3: 00504 case 0xD4: case 0xD5: case 0xD6: case 0xD7: 00505 case 0xD8: case 0xD9: case 0xDA: case 0xDB: 00506 case 0xDE: case 0xDF: 00507 paged=true; indirect=true; break; 00508 case 0xE0: case 0xE1: case 0xE2: case 0xE3: 00509 case 0xE4: case 0xE5: case 0xE6: case 0xE7: 00510 case 0xE8: case 0xE9: case 0xEA: case 0xEB: 00511 case 0xEE: case 0xEF: 00512 idx=sp; xi='S'; break; 00513 } 00514 break; 00515 case 0x32: // use indirect SP indexed or indirect paged Y indexed mode (ST19) 00516 cycles+=2; 00517 ins=Get(pc++); 00518 switch(ins) { 00519 case 0x22: case 0x23: case 0x24: case 0x25: 00520 case 0x26: case 0x27: 00521 vbra=true; indirect=true; break; 00522 case 0xC3: 00523 case 0xCE: case 0xCF: 00524 case 0xD0: case 0xD1: case 0xD2: case 0xD3: 00525 case 0xD4: case 0xD5: case 0xD6: case 0xD7: 00526 case 0xD8: case 0xD9: case 0xDA: case 0xDB: 00527 case 0xDE: case 0xDF: 00528 paged=true; indirect=true; ex=&y; idx=*ex; xs='Y'; xi='Y'; break; 00529 case 0xE0: case 0xE1: case 0xE2: case 0xE3: 00530 case 0xE4: case 0xE5: case 0xE6: case 0xE7: 00531 case 0xE8: case 0xE9: case 0xEA: case 0xEB: 00532 case 0xEE: case 0xEF: 00533 indirect=true; idx=sp; xi='S'; break; 00534 } 00535 break; 00536 case 0x91: // use Y register with indirect addr mode (ST7) 00537 cycles++; 00538 indirect=true; 00539 // fall through 00540 case 0x90: // use Y register (ST7) 00541 cycles++; 00542 ex=&y; idx=*ex; xs='Y'; xi='Y'; 00543 ins=Get(pc++); 00544 break; 00545 case 0x92: // use indirect addr mode (ST7) 00546 cycles+=2; 00547 indirect=true; 00548 ins=Get(pc++); 00549 break; 00550 } 00551 cycles+=clock_cycles[ins]; 00552 int readCycles=clock_cycles[ins]>=2 ? 2:0; 00553 AddCycles(readCycles); 00554 00555 if(doDisAsm) { 00556 char str[8]; 00557 if(!vbra) snprintf(str,sizeof(str),ops[ins],xs,xs^1); 00558 else snprintf(str,sizeof(str),"%s",vops[ins-0x22]); 00559 LOGLBPUT("%-5s ",str); 00560 } 00561 00562 // address decoding 00563 unsigned short ea=0; 00564 unsigned char flags=opFlags[ins]; 00565 unsigned char pr=(flags&4) ? dr:cr; 00566 switch(((flags&8) ? flags:ins)>>4) { 00567 case 0x2: // no or special address mode 00568 case 0x8: 00569 case 0x9: 00570 break; 00571 case 0xA: // immediate 00572 CCLOGLBPUT("#%02x ",Get(pc)); 00573 ea=pc++; break; 00574 case 0x3: // short 00575 case 0xB: 00576 ea=Get(pc++); 00577 if(!indirect) { // short direct 00578 } 00579 else { // short indirect 00580 CCLOGLBPUT("[%02x] -> ",ea); 00581 ea=Get(ea); 00582 } 00583 CCLOGLBPUT("%02x ",ea); 00584 break; 00585 case 0xC: // long 00586 if(!indirect) { // long direct 00587 ea=HILO(pc); pc+=2; 00588 } 00589 else { // long indirect 00590 if(paged) { 00591 ea=HILO(pc); pc+=2; 00592 CCLOGLBPUT("[%s] -> ",PADDR(pr,ea)); 00593 unsigned char s=Get(pr,ea); 00594 ea=HILOS(pr,ea+1); 00595 pr=s; 00596 } 00597 else { 00598 ea=Get(pc++); 00599 CCLOGLBPUT("[%02x] -> ",ea); 00600 ea=HILO(ea); 00601 } 00602 } 00603 CCLOGLBPUT("%s ",PADDR(pr,ea)); 00604 break; 00605 case 0xD: // long indexed 00606 if(!indirect) { // long direct indexed 00607 ea=HILO(pc); pc+=2; 00608 CCLOGLBPUT("(%s",PADDR(cr,ea)); 00609 } 00610 else { // long indirect indexed 00611 if(paged) { 00612 ea=HILO(pc); pc+=2; 00613 CCLOGLBPUT("([%s]",PADDR(pr,ea)); 00614 unsigned char s=Get(pr,ea++); 00615 ea=HILOS(pr,ea); 00616 pr=s; 00617 } 00618 else { 00619 ea=Get(pc++); 00620 CCLOGLBPUT("([%02x]",ea); 00621 ea=HILO(ea); 00622 } 00623 CCLOGLBPUT(",%c) -> (%s",xi,PADDR(pr,ea)); 00624 } 00625 ea+=idx; 00626 CCLOGLBPUT(",%c) -> %s ",xi,PADDR(pr,ea)); 00627 break; 00628 case 0x6: // short indexed 00629 case 0xE: 00630 ea=Get(pc++); 00631 if(!indirect) { // short direct indexed 00632 CCLOGLBPUT("(%02x",ea); 00633 } 00634 else { // short indirect indexed 00635 CCLOGLBPUT("([%02x]",ea); 00636 ea=Get(ea); 00637 CCLOGLBPUT(",%c) -> (%02x",xi,ea); 00638 } 00639 ea+=idx; 00640 CCLOGLBPUT(",%c) -> %s ",xi,PADDR(pr,ea)); 00641 break; 00642 case 0x7: // indexed 00643 case 0xF: 00644 ea=idx; 00645 CCLOGLBPUT("(%c) -> %s ",xi,PADDR(pr,ea)); 00646 break; 00647 case 0x4: // inherent A 00648 CCLOGLBPUT("A "); 00649 break; 00650 case 0x5: // inherent X/Y 00651 CCLOGLBPUT("%c ",xs); 00652 break; 00653 case 0x0: // bit 00654 case 0x1: 00655 ea=Get(pc++); 00656 if(!indirect) { 00657 } 00658 else { 00659 CCLOGLBPUT("[%02x] -> ",ea); 00660 ea=Get(ea); 00661 indirect=false; // don't use indirect mode in case this is a bit branch 00662 } 00663 CCLOGLBPUT("%02x ",ea); 00664 break; 00665 } 00666 00667 // read operant 00668 unsigned char op=0; 00669 if(flags & 1) { 00670 switch(((flags&8) ? flags:ins)>>4) { 00671 case 0x2: // no or special address mode 00672 case 0x8: 00673 case 0x9: 00674 break; 00675 case 0x3: // short 00676 case 0xB: 00677 case 0xC: // long 00678 case 0xD: // long indexed 00679 case 0x6: // short indexed 00680 case 0xE: 00681 case 0x7: // indexed 00682 case 0xF: 00683 case 0x0: // bit 00684 case 0x1: 00685 op=Get(pr,ea); 00686 if(hasReadHandler) ReadHandler(pr,ea,op); 00687 CCLOGLBPUT("{%02x} ",op); 00688 break; 00689 case 0xA: // immediate 00690 op=Get(pr,ea); 00691 break; 00692 case 0x4: // inherent A 00693 op=a; break; 00694 case 0x5: // inherent X/Y 00695 op=*ex; break; 00696 } 00697 } 00698 00699 AddCycles(cycles-readCycles); 00700 00701 // command decoding 00702 stats[ins]++; 00703 switch(ins) { 00704 case 0xA6: // LDA 00705 case 0xB6: 00706 case 0xC6: 00707 case 0xD6: 00708 case 0xE6: 00709 case 0xF6: 00710 a=op; tst(op); break; 00711 case 0xAE: // LDX 00712 case 0xBE: 00713 case 0xCE: 00714 case 0xDE: 00715 case 0xEE: 00716 case 0xFE: 00717 *ex=op; tst(op); break; 00718 case 0xB7: // STA 00719 case 0xC7: 00720 case 0xD7: 00721 case 0xE7: 00722 case 0xF7: 00723 op=a; tst(op); break; 00724 case 0xBF: // STX 00725 case 0xCF: 00726 case 0xDF: 00727 case 0xEF: 00728 case 0xFF: 00729 op=*ex; tst(op); break; 00730 case 0x97: // TAX 00731 *ex=a; break; 00732 case 0x9F: // TXA 00733 a=*ex; break; 00734 case 0x93: // TYX (ST7) 00735 if(ex==&x) *ex=y; else *ex=x; break; 00736 case 0x3D: // TST 00737 case 0x4D: 00738 case 0x5D: 00739 case 0x6D: 00740 case 0x7D: 00741 tst(op); break; 00742 case 0x3F: // CLR 00743 case 0x4F: 00744 case 0x5F: 00745 case 0x6F: 00746 case 0x7F: 00747 op=0; tst(0); break; 00748 case 0x3C: // INC 00749 case 0x4C: 00750 case 0x5C: 00751 case 0x6C: 00752 case 0x7C: 00753 op++; cc.v=(op==0x80); tst(op); break; 00754 case 0x3A: // DEC 00755 case 0x4A: 00756 case 0x5A: 00757 case 0x6A: 00758 case 0x7A: 00759 op--; cc.v=(op==0x7f); tst(op); break; 00760 case 0x33: // COM 00761 case 0x43: 00762 case 0x53: 00763 case 0x63: 00764 case 0x73: 00765 op=~op; cc.c=1; tst(op); break; 00766 case 0x30: // NEG 00767 case 0x40: 00768 case 0x50: 00769 case 0x60: 00770 case 0x70: 00771 op=~op+1; cc.c=(op!=0); cc.v=(op==0x80); tst(op); break; 00772 case 0x42: // MUL 00773 case 0x52: 00774 { 00775 unsigned short res=*ex * a; 00776 *ex=(res>>8); a=res&0xff; cc.c=0; cc.h=0; 00777 break; 00778 } 00779 case 0xA9: // ADC 00780 case 0xB9: 00781 case 0xC9: 00782 case 0xD9: 00783 case 0xE9: 00784 case 0xF9: 00785 a=add(op,cc.c); break; 00786 case 0xAB: // ADD 00787 case 0xBB: 00788 case 0xCB: 00789 case 0xDB: 00790 case 0xEB: 00791 case 0xFB: 00792 a=add(op,0); break; 00793 case 0xA2: // SBC 00794 case 0xB2: 00795 case 0xC2: 00796 case 0xD2: 00797 case 0xE2: 00798 case 0xF2: 00799 a=sub(a,op,cc.c); break; 00800 case 0xA0: // SUB 00801 case 0xB0: 00802 case 0xC0: 00803 case 0xD0: 00804 case 0xE0: 00805 case 0xF0: 00806 a=sub(a,op,0); break; 00807 case 0xA1: // CMP 00808 case 0xB1: 00809 case 0xC1: 00810 case 0xD1: 00811 case 0xE1: 00812 case 0xF1: 00813 sub(a,op,0); break; 00814 case 0xA3: // CPX 00815 case 0xB3: 00816 case 0xC3: 00817 case 0xD3: 00818 case 0xE3: 00819 case 0xF3: 00820 sub(*ex,op,0); break; 00821 case 0xA4: // AND 00822 case 0xB4: 00823 case 0xC4: 00824 case 0xD4: 00825 case 0xE4: 00826 case 0xF4: 00827 a &= op; tst(a); break; 00828 case 0xAA: // ORA 00829 case 0xBA: 00830 case 0xCA: 00831 case 0xDA: 00832 case 0xEA: 00833 case 0xFA: 00834 a |= op; tst(a); break; 00835 case 0xA8: // EOR 00836 case 0xB8: 00837 case 0xC8: 00838 case 0xD8: 00839 case 0xE8: 00840 case 0xF8: 00841 a ^= op; tst(a); break; 00842 case 0xA5: // BIT 00843 case 0xB5: 00844 case 0xC5: 00845 case 0xD5: 00846 case 0xE5: 00847 case 0xF5: 00848 tst(a & op); break; 00849 case 0x38: // ASL 00850 case 0x48: 00851 case 0x58: 00852 case 0x68: 00853 case 0x78: 00854 op=rollL(op,0); break; 00855 case 0x39: // ROL 00856 case 0x49: 00857 case 0x59: 00858 case 0x69: 00859 case 0x79: 00860 op=rollL(op,cc.c); break; 00861 case 0x37: // ASR 00862 case 0x47: 00863 case 0x57: 00864 case 0x67: 00865 case 0x77: 00866 op=rollR(op,bitset(op,7)); break; 00867 case 0x34: // LSR 00868 case 0x44: 00869 case 0x54: 00870 case 0x64: 00871 case 0x74: 00872 op=rollR(op,0); break; 00873 case 0x36: // ROR 00874 case 0x46: 00875 case 0x56: 00876 case 0x66: 00877 case 0x76: 00878 op=rollR(op,cc.c); break; 00879 case 0x3E: // SWAP (ST7) 00880 case 0x4E: 00881 case 0x5E: 00882 case 0x6E: 00883 case 0x7E: 00884 op=(op<<4)|(op>>4); tst(op); break; 00885 //case 0x00 ... 0x0F: // BRSET BRCLR 00886 case 0x00: case 0x01: case 0x02: case 0x03: 00887 case 0x04: case 0x05: case 0x06: case 0x07: 00888 case 0x08: case 0x09: case 0x0A: case 0x0B: 00889 case 0x0C: case 0x0D: case 0x0E: case 0x0F: 00890 { 00891 int bit=(ins&0x0F)>>1; 00892 CCLOGLBPUT(",#%x,",bit); 00893 cc.c=bitset(op,bit); 00894 branch((ins&0x01) ? !cc.c:cc.c); 00895 break; 00896 } 00897 //case 0x10 ... 0x1F: // BSET BCLR 00898 case 0x10: case 0x11: case 0x12: case 0x13: 00899 case 0x14: case 0x15: case 0x16: case 0x17: 00900 case 0x18: case 0x19: case 0x1A: case 0x1B: 00901 case 0x1C: case 0x1D: case 0x1E: case 0x1F: 00902 { 00903 int bit=(ins&0x0F)>>1; 00904 CCLOGLBPUT(",#%x",bit); 00905 if(ins&0x01) op &= ~(1<<bit); 00906 else op |= (1<<bit); 00907 break; 00908 } 00909 case 0x20: // BRA 00910 branch(true); break; 00911 case 0x21: // BRN 00912 branch(false); break; 00913 case 0x22: // BHI 00914 if(vbra) branch(!cc.z && ((cc.n && cc.v) || (!cc.n && !cc.v))); 00915 else branch(!cc.c && !cc.z); 00916 break; 00917 case 0x23: // BLS 00918 if(vbra) branch(cc.z || (cc.n && !cc.v) || (!cc.n && cc.v)); 00919 else branch( cc.c || cc.z); 00920 break; 00921 case 0x24: // BCC BHS 00922 if(vbra) branch((cc.n && cc.v) || (!cc.n && !cc.v)); 00923 else branch(!cc.c); 00924 break; 00925 case 0x25: // BCS BLO 00926 if(vbra) branch((cc.n && !cc.v) || (!cc.n && cc.v)); 00927 else branch( cc.c); 00928 break; 00929 case 0x26: // BNE 00930 if(vbra) branch(!cc.v); 00931 else branch(!cc.z); 00932 break; 00933 case 0x27: // BEQ 00934 if(vbra) branch(cc.v); 00935 else branch( cc.z); break; 00936 case 0x28: // BHCC 00937 branch(!cc.h); break; 00938 case 0x29: // BHCS 00939 branch( cc.h); break; 00940 case 0x2A: // BPL 00941 branch(!cc.n); break; 00942 case 0x2B: // BMI 00943 branch( cc.n); break; 00944 case 0x2C: // BMC 00945 branch(!cc.i); break; 00946 case 0x2D: // BMS 00947 branch( cc.i); break; 00948 case 0xBC: // JMP 00949 case 0xCC: 00950 case 0xDC: 00951 case 0xEC: 00952 case 0xFC: 00953 pc=ea; break; 00954 case 0xAD: // BSR 00955 pc++; pushpc(); pc--; branch(true); break; 00956 case 0xBD: // JSR 00957 case 0xCD: 00958 case 0xDD: 00959 case 0xED: 00960 case 0xFD: 00961 pushpc(); pc=ea; break; 00962 case 0x81: // RTS 00963 poppc(); break; 00964 case 0x83: // SWI 00965 pushpc(); push(x); push(a); pushc(); 00966 cc.i=1; pc=HILO(0x1ffc); break; 00967 case 0x80: // RTI 00968 popc(); a=pop(); x=pop(); poppc(); break; 00969 case 0x9C: // RSP 00970 sp=spHi; break; 00971 case 0x96: // TSX 00972 *ex=sp&0xFF; break; 00973 case 0x94: // TXS (ST7) 00974 sp=(sp&0xFF00)|*ex; break; 00975 case 0x9E: // TSA 00976 a=sp&0xFF; break; 00977 case 0x95: // TAS (ST7) 00978 sp=(sp&0xFF00)|a; break; 00979 case 0x84: // POPA (ST7) 00980 a=pop(); break; 00981 case 0x85: // POPX (ST7) 00982 *ex=pop(); break; 00983 case 0x86: // POPC (ST7) 00984 popc(); break; 00985 case 0x88: // PUSHA (ST7) 00986 push(a); break; 00987 case 0x89: // PUSHX (ST7) 00988 push(*ex); break; 00989 case 0x8A: // PUSHC (ST7) 00990 pushc(); break; 00991 case 0x98: // CLC 00992 cc.c=0; break; 00993 case 0x99: // SEC 00994 cc.c=1; break; 00995 case 0x9A: // CLI 00996 cc.i=0; break; 00997 case 0x9B: // SEI 00998 cc.i=1; break; 00999 case 0x9D: // NOP 01000 break; 01001 01002 case 0x71: // LDD (ST19) 01003 case 0x72: 01004 case 0x75: 01005 dr=op; break; 01006 case 0x7B: // TAD (ST19) 01007 dr=a; break; 01008 case 0x8B: // TDA (ST19) 01009 a=dr; break; 01010 case 0x8C: // TCA (ST19) 01011 a=cr; break; 01012 case 0xAC: // PUSHD (ST19) 01013 push(dr); break; 01014 case 0xAF: // POPD (ST19) 01015 dr=pop(); break; 01016 case 0x87: // PRTS (ST19) 01017 cr=pop(); poppc(); break; 01018 case 0x8D: // PJSR (ST19) 01019 if(paged) { 01020 ea=HILO(pc); pc+=2; 01021 CCLOGLBPUT("[%s] -> ",PADDR(cr,ea)); 01022 } 01023 else { 01024 ea=pc; pc+=3; 01025 } 01026 pr=Get(ea++); 01027 ea=HILO(ea); 01028 CCLOGLBPUT("%s ",PADDR(pr,ea)); 01029 pushpc(); push(cr); cr=pr; pc=ea; break; 01030 01031 case 0x90: // pre-bytes 01032 case 0x91: 01033 case 0x92: 01034 case 0x31: 01035 case 0x32: 01036 PRINTF(L_SYS_EMU,"pre-byte %02x in command decoding (count=%d)",ins,count); 01037 loglb->cLineBuff::Flush(); 01038 return 3; 01039 default: 01040 PRINTF(L_SYS_EMU,"unsupported instruction 0x%02x (count=%d)",ins,count); 01041 loglb->cLineBuff::Flush(); 01042 return 3; 01043 } 01044 01045 // write operant 01046 if(flags & 2) { 01047 switch(((flags&8) ? flags:ins)>>4) { 01048 case 0x2: // no or special address mode 01049 case 0x8: 01050 case 0x9: 01051 break; 01052 case 0xA: // immediate 01053 case 0x3: // short 01054 case 0xB: 01055 case 0xC: // long 01056 case 0xD: // long indexed 01057 case 0x6: // short indexed 01058 case 0xE: 01059 case 0x7: // indexed 01060 case 0xF: 01061 case 0x0: // bit 01062 case 0x1: 01063 Set(ea,op); break; 01064 case 0x4: // inherent A 01065 a=op; break; 01066 case 0x5: // inherent X/Y 01067 *ex=op; break; 01068 } 01069 } 01070 if(doDisAsm) PUTLB(disAsmLogClass,loglb); 01071 else loglb->cLineBuff::Flush(); 01072 01073 for(int i=numBp-1 ; i>=0 ; i--) { 01074 if(bp[i]==pc) { 01075 PRINTF(L_SYS_EMU,"6805: breakpoint at %04x (count=%d)",pc,count); 01076 return 0; 01077 } 01078 } 01079 if(count>=max_count) { 01080 PRINTF(L_SYS_EMU,"max. instruction counter exceeded (count=%d)",count); 01081 return 2; 01082 } 01083 } 01084 } 01085 01086 void c6805::branch(bool branch) 01087 { 01088 if(doDisAsm) { 01089 unsigned char off=Get(pc); 01090 if(indirect) { 01091 LOGLBPUT("[%02x] -> ",off); 01092 off=Get(off); 01093 } 01094 unsigned short npc=pc+off+1; 01095 if(off&0x80) npc-=0x100; // gcc fixup. take care of sign 01096 LOGLBPUT("%s ",PADDR(cr,npc)); 01097 if(branch) LOGLBPUT("(taken) "); 01098 } 01099 pc++; 01100 if(branch) { 01101 unsigned char offset=Get(pc-1); 01102 if(indirect) offset=Get(offset); 01103 pc+=offset; 01104 if(offset&0x80) pc-=0x100; // gcc fixup. take care of sign 01105 } 01106 } 01107 01108 void c6805::push(unsigned char c) 01109 { 01110 Set(sp--,c); 01111 } 01112 01113 unsigned char c6805::pop(void) 01114 { 01115 return Get(++sp); 01116 } 01117 01118 void c6805::pushpc(void) 01119 { 01120 push(pc & 0xff); 01121 push(pc >> 8); 01122 } 01123 01124 void c6805::poppc(void) 01125 { 01126 pc=(pop()<<8) | pop(); 01127 } 01128 01129 void c6805::pushc(void) 01130 { 01131 unsigned char c=0xC0+(cc.v?32:0)+(cc.h?16:0)+(cc.i?8:0)+(cc.n?4:0)+(cc.z?2:0)+(cc.c?1:0); 01132 push(c); 01133 } 01134 01135 void c6805::popc(void) 01136 { 01137 unsigned char c=pop(); 01138 cc.v=(c&32) ? 1:0; 01139 cc.h=(c&16) ? 1:0; 01140 cc.i=(c& 8) ? 1:0; 01141 cc.n=(c& 4) ? 1:0; 01142 cc.z=(c& 2) ? 1:0; 01143 cc.c=(c& 1) ? 1:0; 01144 } 01145 01146 void c6805::tst(unsigned char c) 01147 { 01148 cc.z=!c; 01149 cc.n=bitset(c,7); 01150 } 01151 01152 unsigned char c6805::add(unsigned char op, unsigned char c) 01153 { 01154 unsigned short res_half=(a&0x0f) + (op&0x0f) + c; 01155 unsigned short res=(unsigned short)a + (unsigned short)op + (unsigned short)c; 01156 cc.h=res_half > 0x0f; 01157 cc.c=res > 0xff; 01158 res&=0xff; 01159 cc.v=((op+c)&0x80) ? ((a&0x80) && !(res&0x80)) : (!(a&0x80) && (res&0x80)); 01160 tst(res); 01161 return res; 01162 } 01163 01164 unsigned char c6805::sub(unsigned char op1, unsigned char op2, unsigned char c) 01165 { 01166 short res=(short)op1 - (short)op2 - (short)c; 01167 cc.c=res < 0; 01168 res&=0xff; 01169 cc.v=((op2+c)&0x80) ? (!(op1&0x80) && (res&0x80)) : ((op1&0x80) && !(res&0x80)); 01170 tst(res); 01171 return res; 01172 } 01173 01174 unsigned char c6805::rollR(unsigned char op, unsigned char c) 01175 { 01176 cc.c=bitset(op,0); 01177 op >>= 1; 01178 op |= c << 7; 01179 tst(op); 01180 return op; 01181 } 01182 01183 unsigned char c6805::rollL(unsigned char op, unsigned char c) 01184 { 01185 cc.c=bitset(op,7); 01186 op <<= 1; 01187 op |= c; 01188 tst(op); 01189 return op; 01190 }