📄 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 + -