📄 cpu.c
字号:
OPCODE(b5) /* LDA ab,x */ ZPAGE_X; LDA(dGetByte(addr)); DONE OPCODE(b6) /* LDX ab,y */ ZPAGE_Y; LDX(GetByte(addr)); DONE OPCODE(b7) /* LAX ab,y [unofficial] */ ZPAGE_Y; Z = N = X = A = GetByte(addr); DONE OPCODE(b8) /* CLV */#ifndef NO_V_FLAG_VARIABLE V = 0;#else ClrV;#endif DONE OPCODE(b9) /* LDA abcd,y */ ABSOLUTE_Y; NCYCLES_Y; LDA(GetByte(addr)); DONE OPCODE(ba) /* TSX */ Z = N = X = S; DONE/* AXA [unofficial - original decode by R.Sterba and R.Petruzela 15.1.1998 :-)] AXA - this is our new imaginative name for instruction with opcode hex BB. AXA - Store Mem AND #$FD to Acc and X, then set stackpoint to value (Acc - 4) It's cool! :-) LAS - this is better name for this :) (Fox) It simply ANDs stack pointer with Mem, then transfers result to A and X */ OPCODE(bb) /* LAS abcd,y [unofficial - AND S with Mem, transfer to A and X (Fox) */ ABSOLUTE_Y; NCYCLES_Y; Z = N = A = X = S &= GetByte(addr); DONE OPCODE(bc) /* LDY abcd,x */ ABSOLUTE_X; NCYCLES_X; LDY(GetByte(addr)); DONE OPCODE(bd) /* LDA abcd,x */ ABSOLUTE_X; NCYCLES_X; LDA(GetByte(addr)); DONE OPCODE(be) /* LDX abcd,y */ ABSOLUTE_Y; NCYCLES_Y; LDX(GetByte(addr)); DONE OPCODE(bf) /* LAX abcd,y [unofficial] */ ABSOLUTE_Y; NCYCLES_Y; Z = N = X = A = GetByte(addr); DONE OPCODE(c0) /* CPY #ab */ CPY(IMMEDIATE); DONE OPCODE(c1) /* CMP (ab,x) */ INDIRECT_X; CMP(GetByte(addr)); DONE OPCODE(c3) /* DCM (ab,x) [unofficial - DEC Mem then CMP with Acc] */ INDIRECT_X; dcm: RMW_GetByte(data, addr); data--; PutByte(addr, data); CMP(data); DONE OPCODE(c4) /* CPY ab */ ZPAGE; CPY(dGetByte(addr)); DONE OPCODE(c5) /* CMP ab */ ZPAGE; CMP(dGetByte(addr)); DONE OPCODE(c6) /* DEC ab */ ZPAGE; Z = N = dGetByte(addr) - 1; dPutByte(addr, Z); DONE OPCODE(c7) /* DCM ab [unofficial - DEC Mem then CMP with Acc] */ ZPAGE; dcm_zpage: data = dGetByte(addr) - 1; dPutByte(addr, data); CMP(data); DONE OPCODE(c8) /* INY */ Z = N = ++Y; DONE OPCODE(c9) /* CMP #ab */ CMP(IMMEDIATE); DONE OPCODE(ca) /* DEX */ Z = N = --X; DONE OPCODE(cb) /* SBX #ab [unofficial - store ((A AND X) - Mem) in X] (Fox) */ X &= A; data = IMMEDIATE; C = X >= data; /* MPC 05/24/00 */ Z = N = X -= data; DONE OPCODE(cc) /* CPY abcd */ ABSOLUTE; CPY(GetByte(addr)); DONE OPCODE(cd) /* CMP abcd */ ABSOLUTE; CMP(GetByte(addr)); DONE OPCODE(ce) /* DEC abcd */ ABSOLUTE; RMW_GetByte(Z, addr); N = --Z; PutByte(addr, Z); DONE OPCODE(cf) /* DCM abcd [unofficial - DEC Mem then CMP with Acc] */ ABSOLUTE; goto dcm; OPCODE(d0) /* BNE */ BRANCH(Z) OPCODE(d1) /* CMP (ab),y */ INDIRECT_Y; NCYCLES_Y; CMP(GetByte(addr)); DONE OPCODE(d3) /* DCM (ab),y [unofficial - DEC Mem then CMP with Acc] */ INDIRECT_Y; goto dcm; OPCODE(d5) /* CMP ab,x */ ZPAGE_X; CMP(dGetByte(addr)); Z = N = A - data; C = (A >= data); DONE OPCODE(d6) /* DEC ab,x */ ZPAGE_X; Z = N = dGetByte(addr) - 1; dPutByte(addr, Z); DONE OPCODE(d7) /* DCM ab,x [unofficial - DEC Mem then CMP with Acc] */ ZPAGE_X; goto dcm_zpage; OPCODE(d8) /* CLD */ ClrD; DONE OPCODE(d9) /* CMP abcd,y */ ABSOLUTE_Y; NCYCLES_Y; CMP(GetByte(addr)); DONE OPCODE(db) /* DCM abcd,y [unofficial - DEC Mem then CMP with Acc] */ ABSOLUTE_Y; goto dcm; OPCODE(dd) /* CMP abcd,x */ ABSOLUTE_X; NCYCLES_X; CMP(GetByte(addr)); DONE OPCODE(de) /* DEC abcd,x */ ABSOLUTE_X; RMW_GetByte(Z, addr); N = --Z; PutByte(addr, Z); DONE OPCODE(df) /* DCM abcd,x [unofficial - DEC Mem then CMP with Acc] */ ABSOLUTE_X; goto dcm; OPCODE(e0) /* CPX #ab */ CPX(IMMEDIATE); DONE OPCODE(e1) /* SBC (ab,x) */ INDIRECT_X; data = GetByte(addr); goto sbc; OPCODE(e3) /* INS (ab,x) [unofficial - INC Mem then SBC with Acc] */ INDIRECT_X; ins: RMW_GetByte(data, addr); ++data; PutByte(addr, data); goto sbc; OPCODE(e4) /* CPX ab */ ZPAGE; CPX(dGetByte(addr)); DONE OPCODE(e5) /* SBC ab */ ZPAGE; data = dGetByte(addr); goto sbc; OPCODE(e6) /* INC ab */ ZPAGE; Z = N = dGetByte(addr) + 1; dPutByte(addr, Z); DONE OPCODE(e7) /* INS ab [unofficial - INC Mem then SBC with Acc] */ ZPAGE; ins_zpage: data = dGetByte(addr) + 1; dPutByte(addr, data); goto sbc; OPCODE(e8) /* INX */ Z = N = ++X; DONE OPCODE_ALIAS(e9) /* SBC #ab */ OPCODE(eb) /* SBC #ab [unofficial] */ data = IMMEDIATE; goto sbc; OPCODE_ALIAS(ea) /* NOP */ OPCODE_ALIAS(1a) /* NOP [unofficial] */ OPCODE_ALIAS(3a) OPCODE_ALIAS(5a) OPCODE_ALIAS(7a) OPCODE_ALIAS(da) OPCODE(fa) DONE OPCODE(ec) /* CPX abcd */ ABSOLUTE; CPX(GetByte(addr)); DONE OPCODE(ed) /* SBC abcd */ ABSOLUTE; data = GetByte(addr); goto sbc; OPCODE(ee) /* INC abcd */ ABSOLUTE; RMW_GetByte(Z, addr); N = ++Z; PutByte(addr, Z); DONE OPCODE(ef) /* INS abcd [unofficial - INC Mem then SBC with Acc] */ ABSOLUTE; goto ins; OPCODE(f0) /* BEQ */ BRANCH(!Z) OPCODE(f1) /* SBC (ab),y */ INDIRECT_Y; NCYCLES_Y; data = GetByte(addr); goto sbc; OPCODE(f3) /* INS (ab),y [unofficial - INC Mem then SBC with Acc] */ INDIRECT_Y; goto ins; OPCODE(f5) /* SBC ab,x */ ZPAGE_X; data = dGetByte(addr); goto sbc; OPCODE(f6) /* INC ab,x */ ZPAGE_X; Z = N = dGetByte(addr) + 1; dPutByte(addr, Z); DONE OPCODE(f7) /* INS ab,x [unofficial - INC Mem then SBC with Acc] */ ZPAGE_X; goto ins_zpage; OPCODE(f8) /* SED */ SetD; DONE OPCODE(f9) /* SBC abcd,y */ ABSOLUTE_Y; NCYCLES_Y; data = GetByte(addr); goto sbc; OPCODE(fb) /* INS abcd,y [unofficial - INC Mem then SBC with Acc] */ ABSOLUTE_Y; goto ins; OPCODE(fd) /* SBC abcd,x */ ABSOLUTE_X; NCYCLES_X; data = GetByte(addr); goto sbc; OPCODE(fe) /* INC abcd,x */ ABSOLUTE_X; RMW_GetByte(Z, addr); N = ++Z; PutByte(addr, Z); DONE OPCODE(ff) /* INS abcd,x [unofficial - INC Mem then SBC with Acc] */ ABSOLUTE_X; goto ins;#ifdef ASAP OPCODE_ALIAS(d2) OPCODE_ALIAS(f2)#else OPCODE(d2) /* ESCRTS #ab (CIM) - on Atari is here instruction CIM [unofficial] !RS! */ data = IMMEDIATE; UPDATE_GLOBAL_REGS; CPU_GetStatus(); Atari800_RunEsc(data); CPU_PutStatus(); UPDATE_LOCAL_REGS; data = PL; SET_PC((PL << 8) + data + 1);#ifdef MONITOR_BREAK if (break_ret && --ret_nesting <= 0) break_step = TRUE;#endif DONE OPCODE(f2) /* ESC #ab (CIM) - on Atari is here instruction CIM [unofficial] !RS! */ /* OPCODE(ff: ESC #ab - opcode FF is now used for INS [unofficial] instruction !RS! */ data = IMMEDIATE; UPDATE_GLOBAL_REGS; CPU_GetStatus(); Atari800_RunEsc(data); CPU_PutStatus(); UPDATE_LOCAL_REGS; DONE#endif /* ASAP */ OPCODE_ALIAS(02) /* CIM [unofficial - crash intermediate] */ OPCODE_ALIAS(12) OPCODE_ALIAS(22) OPCODE_ALIAS(32) OPCODE_ALIAS(42) OPCODE_ALIAS(52) OPCODE_ALIAS(62) OPCODE_ALIAS(72) OPCODE_ALIAS(92) OPCODE(b2)#ifdef ASAP ASAP_CIM(); DONE#else /* OPCODE(d2) Used for ESCRTS #ab (CIM) */ /* OPCODE(f2) Used for ESC #ab (CIM) */ PC--; UPDATE_GLOBAL_REGS; CPU_GetStatus();#ifdef CRASH_MENU crash_address = GET_PC(); crash_afterCIM = GET_PC() + 1; crash_code = insn; ui();#else cim_encountered = TRUE; ENTER_MONITOR;#endif /* CRASH_MENU */ CPU_PutStatus(); UPDATE_LOCAL_REGS; DONE#endif /* ASAP *//* ---------------------------------------------- *//* ADC and SBC routines */ adc: if (!(regP & D_FLAG)) { /* Binary mode */ unsigned int tmp; tmp = A + data + C; C = tmp > 0xff; /* C = tmp >> 8; */#ifndef NO_V_FLAG_VARIABLE V = !((A ^ data) & 0x80) && ((data ^ tmp) & 0x80);#else ClrV; if (!((A ^ data) & 0x80) && ((data ^ tmp) & 0x80)) SetV;#endif Z = N = A = (UBYTE) tmp; } else { /* Decimal mode */ unsigned int tmp; tmp = (A & 0x0f) + (data & 0x0f) + C; if (tmp >= 10) tmp = (tmp - 10) | 0x10; tmp += (A & 0xf0) + (data & 0xf0); Z = A + data + C; N = (UBYTE) tmp;#ifndef NO_V_FLAG_VARIABLE V = !((A ^ data) & 0x80) && ((data ^ tmp) & 0x80);#else ClrV; if (!((A ^ data) & 0x80) && ((data ^ tmp) & 0x80)) SetV;#endif if (tmp > 0x9f) tmp += 0x60; C = tmp > 0xff; A = (UBYTE) tmp; } DONE sbc: if (!(regP & D_FLAG)) { /* Binary mode */ unsigned int tmp; /* tmp = A - data - !C; */ tmp = A - data - 1 + C; C = tmp < 0x100;#ifndef NO_V_FLAG_VARIABLE V = ((A ^ tmp) & 0x80) && ((A ^ data) & 0x80);#else ClrV; if (((A ^ tmp) & 0x80) && ((A ^ data) & 0x80)) SetV;#endif Z = N = A = (UBYTE) tmp; } else { /* Decimal mode */ unsigned int al, ah, tmp; /* tmp = A - data - !C; */ tmp = A - data - 1 + C; /* al = (A & 0x0f) - (data & 0x0f) - !C; */ al = (A & 0x0f) - (data & 0x0f) - 1 + C; /* Calculate lower nybble */ ah = (A >> 4) - (data >> 4); /* Calculate upper nybble */ if (al & 0x10) { al -= 6; /* BCD fixup for lower nybble */ ah--; } if (ah & 0x10) ah -= 6; /* BCD fixup for upper nybble */ C = tmp < 0x100; /* Set flags */#ifndef NO_V_FLAG_VARIABLE V = ((A ^ tmp) & 0x80) && ((A ^ data) & 0x80);#else ClrV; if (((A ^ tmp) & 0x80) && ((A ^ data) & 0x80)) SetV;#endif Z = N = (UBYTE) tmp; A = (ah << 4) + (al & 0x0f); /* Compose result */ } DONE#ifdef NO_GOTO }#else next:#endif#ifdef MONITOR_BREAK if (break_step) { DO_BREAK; }#endif /* This "continue" does nothing here. But it is necessary because, if we're not using NO_GOTO nor MONITOR_BREAK, gcc can complain: "error: label at end of compound statement". */ continue; } UPDATE_GLOBAL_REGS;}void CPU_Initialise(void){}#endif /* FALCON_CPUASM */void CPU_Reset(void){#ifdef MONITOR_PROFILE memset(instruction_count, 0, sizeof(instruction_count));#endif IRQ = 0; regP = 0x34; /* The unused bit is always 1, I flag set! */ CPU_PutStatus(); /* Make sure flags are all updated */ regS = 0xff; regPC = dGetWordAligned(0xfffc);}#if !defined(BASIC) && !defined(ASAP)void CpuStateSave(UBYTE SaveVerbose){ SaveUBYTE(®A, 1); CPU_GetStatus(); /* Make sure flags are all updated */ SaveUBYTE(®P, 1); SaveUBYTE(®S, 1); SaveUBYTE(®X, 1); SaveUBYTE(®Y, 1); SaveUBYTE(&IRQ, 1); MemStateSave(SaveVerbose); SaveUWORD(®PC, 1);}void CpuStateRead(UBYTE SaveVerbose){ ReadUBYTE(®A, 1); ReadUBYTE(®P, 1); CPU_PutStatus(); /* Make sure flags are all updated */ ReadUBYTE(®S, 1); ReadUBYTE(®X, 1); ReadUBYTE(®Y, 1); ReadUBYTE(&IRQ, 1); MemStateRead( SaveVerbose ); ReadUWORD(®PC, 1);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -