/* Macros for setting/clearing program status register bits */ #define F_setN(v) if (v) P |= 0x80; else P &= ~0x80 #define F_setV(v) if (v) P |= 0x40; else P &= ~0x40 #define F_setM(v) if (v) P |= 0x20; else P &= ~0x20 #define F_setX(v) if (v) P |= 0x10; else P &= ~0x10 #define F_setD(v) if (v) P |= 0x08; else P &= ~0x08 #define F_setI(v) if (v) P |= 0x04; else P &= ~0x04 #define F_setZ(v) if (v) P |= 0x02; else P &= ~0x02 #define F_setC(v) if (v) P |= 0x01; else P &= ~0x01 /* Macros for testing program status register bits */ #define F_getN ((P & 0x80)? 1:0) #define F_getV ((P & 0x40)? 1:0) #define F_getM ((P & 0x20)? 1:0) #define F_getX ((P & 0x10)? 1:0) #define F_getD ((P & 0x08)? 1:0) #define F_getI ((P & 0x04)? 1:0) #define F_getZ ((P & 0x02)? 1:0) #define F_getC ((P & 0x01)? 1:0) #define F_getE (E? 1:0) /*------- Routines that operate on an 8/16-bit value -------*/ #define C_SETF8(v) F_setN(v & 0x80); \ F_setZ(!v) #define C_SETF16(v) F_setN(v & 0x8000); \ F_setZ(!v) #define C_LDA8(v) A.B.L = v; \ C_SETF8(v) #define C_LDA16(v) A.W = v; \ C_SETF16(v) #define C_LDX8(v) X.B.L = v; \ C_SETF8(v) #define C_LDX16(v) X.W = v; \ C_SETF16(v) #define C_LDY8(v) Y.B.L = v; \ C_SETF8(v) #define C_LDY16(v) Y.W = v; \ C_SETF16(v) #define C_INC8(v) v++; \ C_SETF8(v) #define C_INC16(v) v++; \ C_SETF16(v) #define C_DEC8(v) v--; \ C_SETF8(v) #define C_DEC16(v) v--; \ C_SETF16(v) #define C_ASL8(v) F_setC(v & 0x80); \ v = v << 1; \ C_SETF8(v) #define C_ASL16(v) F_setC(v & 0x8000); \ v = v << 1; \ C_SETF16(v) #define C_LSR8(v) F_setC(v & 0x01); \ v = v >> 1; \ C_SETF8(v) #define C_LSR16(v) F_setC(v & 0x0001); \ v = v >> 1; \ C_SETF16(v) #define C_ROL8(v) wtmp.B.L = P & 0x01; \ F_setC(v & 0x80); \ v = (v << 1) | wtmp.B.L; \ C_SETF8(v) #define C_ROL16(v) wtmp.W = P & 0x01; \ F_setC(v & 0x8000); \ v = (v << 1) | wtmp.W; \ C_SETF16(v) #define C_ROR8(v) wtmp.B.L = (P & 0x01) << 7; \ F_setC(v & 0x01); \ v = (v >> 1) | wtmp.B.L; \ C_SETF8(v) #define C_ROR16(v) wtmp.W = (P & 0x01) << 15; \ F_setC(v & 0x0001); \ v = (v >> 1) | wtmp.W; \ C_SETF16(v) #define C_AND8(v) A.B.L &= v; \ C_SETF8(A.B.L) #define C_AND16(v) A.W &= v; \ C_SETF16(A.W) #define C_ORA8(v) A.B.L |= v; \ C_SETF8(A.B.L) #define C_ORA16(v) A.W |= v; \ C_SETF16(A.W) #define C_EOR8(v) A.B.L ^= v; \ C_SETF8(A.B.L) #define C_EOR16(v) A.W ^= v; \ C_SETF16(A.W) #define C_TSB8(v) F_setN(v & 0x80); \ F_setV(v & 0x40); \ v |= A.B.L; \ F_setZ(!v) #define C_TSB16(v) F_setN(v & 0x8000); \ F_setV(v & 0x4000); \ v |= A.W; \ F_setZ(!v) #define C_TRB8(v) F_setN(v & 0x80); \ F_setV(v & 0x40); \ v &= ~A.B.L; \ F_setZ(!v) #define C_TRB16(v) F_setN(v & 0x8000); \ F_setV(v & 0x4000); \ v &= ~A.W; \ F_setZ(!v) #define C_BIT8(v) F_setN(v & 0x80); \ F_setV(v & 0x40); \ F_setZ(!(v & A.B.L)); \ #define C_BIT16(v) F_setN(v & 0x8000); \ F_setV(v & 0x4000); \ F_setZ(!(v & A.W)); \ #define C_ADC8(v) if (F_getD) { \ printf("WARNING -- decimal mode ADC attempted!\n"); \ } else { \ wtmp.W = A.B.L + v + F_getC; \ F_setV(~(A.B.L ^ v) & (A.B.L ^ wtmp.B.L) & 0x80); \ F_setC(wtmp.B.H); \ A.B.L = wtmp.B.L; \ C_SETF8(A.B.L); \ } #define C_ADC16(v) if (F_getD) { \ printf("WARNING -- decimal mode ADC attempted!\n"); \ } else { \ atmp.A = A.W + v + F_getC; \ F_setV(~(A.W ^ v) & (A.W ^ atmp.A) & 0x8000); \ F_setC(atmp.B.B); \ A.W = atmp.A; \ C_SETF16(A.W); \ } #define C_SBC8(v) if (F_getD) { \ printf("WARNING -- decimal mode SBC attempted!\n"); \ } else { \ wtmp.W = (A.B.L - v) - !F_getC; \ F_setV((A.B.L ^ v) & (A.B.L ^ wtmp.B.L) & 0x80); \ F_setC(!wtmp.B.H); \ A.B.L = wtmp.B.L; \ C_SETF8(A.B.L); \ } #define C_SBC16(v) if (F_getD) { \ printf("WARNING -- decimal mode SBC attempted!\n"); \ } else { \ atmp.A = (A.W - v) - !F_getC; \ F_setV((A.W ^ v) & (A.W ^ atmp.A) & 0x8000); \ F_setC(!atmp.B.B); \ A.W = atmp.A; \ C_SETF16(A.W); \ } #define C_CMP8(v) wtmp.W = A.B.L - v; \ F_setC(!wtmp.B.H); \ C_SETF8(wtmp.B.L) #define C_CMP16(v) atmp.A = A.W - v; \ F_setC(!atmp.B.B); \ atmp.B.B = 0; \ C_SETF16(atmp.A) #define C_CPX8(v) wtmp.W = X.B.L - v; \ F_setC(!wtmp.B.H); \ C_SETF8(wtmp.B.L) #define C_CPX16(v) atmp.A = X.W - v; \ F_setC(!atmp.B.B); \ atmp.B.B = 0; \ C_SETF16(atmp.A) #define C_CPY8(v) wtmp.W = Y.B.L - v; \ F_setC(!wtmp.B.H); \ C_SETF8(wtmp.B.L) #define C_CPY16(v) atmp.A = Y.W - v; \ F_setC(!atmp.B.B); \ atmp.B.B = 0; \ C_SETF16(atmp.A) /*------- Routines that operate on a memory address -------*/ #define C_LDA(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_LDA8(otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_LDA16(otmp.W); \ } #define C_LDX(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_LDX8(otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_LDX16(otmp.W); \ } #define C_LDY(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_LDY8(otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_LDY16(otmp.W); \ } #define C_STA(a) M_WRITE(a.A,A.B.L); \ if (!F_getM) M_WRITE(a.A+1,A.B.H) #define C_STX(a) M_WRITE(a.A,X.B.L); \ if (!F_getX) M_WRITE(a.A+1,X.B.H) #define C_STY(a) M_WRITE(a.A,Y.B.L); \ if (!F_getX) M_WRITE(a.A+1,Y.B.H) #define C_STZ(a) M_WRITE(a.A,0); \ if (!F_getM) M_WRITE(a.A+1,0) #define C_INC(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_INC8(otmp.B.L); \ M_WRITE(a.A,otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_INC16(otmp.W); \ M_WRITE(a.A,otmp.B.L); \ M_WRITE(a.A+1,otmp.B.H); \ } #define C_DEC(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_DEC8(otmp.B.L); \ M_WRITE(a.A,otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_DEC16(otmp.W); \ M_WRITE(a.A,otmp.B.L); \ M_WRITE(a.A+1,otmp.B.H); \ } #define C_ASL(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_ASL8(otmp.B.L); \ M_WRITE(a.A,otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_ASL16(otmp.W); \ M_WRITE(a.A,otmp.B.L); \ M_WRITE(a.A+1,otmp.B.H); \ } #define C_LSR(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_LSR8(otmp.B.L); \ M_WRITE(a.A,otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_LSR16(otmp.W); \ M_WRITE(a.A,otmp.B.L); \ M_WRITE(a.A+1,otmp.B.H); \ } #define C_ROL(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_ROL8(otmp.B.L); \ M_WRITE(a.A,otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_ROL16(otmp.W); \ M_WRITE(a.A,otmp.B.L); \ M_WRITE(a.A+1,otmp.B.H); \ } #define C_ROR(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_ROR8(otmp.B.L); \ M_WRITE(a.A,otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_ROR16(otmp.W); \ M_WRITE(a.A,otmp.B.L); \ M_WRITE(a.A+1,otmp.B.H); \ } #define C_AND(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_AND8(otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_AND16(otmp.W); \ } #define C_ORA(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_ORA8(otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_ORA16(otmp.W); \ } #define C_EOR(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_EOR8(otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_EOR16(otmp.W); \ } #define C_TSB(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_TSB8(otmp.B.L); \ M_WRITE(a.A,otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_TSB16(otmp.W); \ M_WRITE(a.A,otmp.B.L); \ M_WRITE(a.A+1,otmp.B.H); \ } #define C_TRB(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_TRB8(otmp.B.L); \ M_WRITE(a.A,otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_TRB16(otmp.W); \ M_WRITE(a.A,otmp.B.L); \ M_WRITE(a.A+1,otmp.B.H); \ } #define C_BIT(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_BIT8(otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_BIT16(otmp.W); \ } #define C_ADC(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_ADC8(otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_ADC16(otmp.W); \ } #define C_SBC(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_SBC8(otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_SBC16(otmp.W); \ } #define C_CMP(a) otmp.B.L = M_READ(a.A); \ if (F_getM) { \ C_CMP8(otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_CMP16(otmp.W); \ } #define C_CPX(a) otmp.B.L = M_READ(a.A); \ if (F_getX) { \ C_CPX8(otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_CPX16(otmp.W); \ } #define C_CPY(a) otmp.B.L = M_READ(a.A); \ if (F_getX) { \ C_CPY8(otmp.B.L); \ } else { \ otmp.B.H = M_READ(a.A+1); \ C_CPY16(otmp.W); \ } /* Macros for pushing or pulling bytes on the 65816 stack */ #define S_PUSH(v) M_WRITE(S.W--,v); if (F_getE) S.B.H = 1; #define S_PULL(v) v = M_READ(++S.W); if (F_getE) S.B.H = 1; /* Macros to retrieve an 8 or 16-bit operand. They take as their parameter */ /* a "dualw" union variable, which they set to the operand. */ #define O_i8(v) v.B.L = M_READ(PC.W++); v.B.H = 0 #define O_i16(v) v.B.L = M_READ(PC.W++); v.B.H = M_READ(PC.W++) /* Macros to retrieve the operand address. These take as their parameter */ /* a "duala" union variable, which they set to the operand address. */ #define O_a(a) a.B.L = M_READ(PC.W++); a.B.H = M_READ(PC.W++); a.B.B = DB #define O_al(a) a.B.L = M_READ(PC.W++); a.B.H = M_READ(PC.W++); a.B.B = M_READ(PC.W++) #define O_d(a) a.A = D.W + M_READ(PC.W++); a.B.B = 0 #define O_dix(a) atmp.A = D.W + M_READ(PC.W++); a.B.B = 0; \ a.B.L = M_READ(atmp.A); a.B.H = M_READ(atmp.A+1); a.B.B = DB; \ a.A += Y.W #define O_dixl(a) atmp.A = D.W + M_READ(PC.W++); a.B.B = 0; \ a.B.L = M_READ(atmp.A); a.B.H = M_READ(atmp.A+1); a.B.B = M_READ(atmp.A+2); \ a.A += Y.W #define O_dxi(a) atmp.A = D.W + M_READ(PC.W++) + X.W; a.B.B = 0; \ a.B.L = M_READ(atmp.A); a.B.H = M_READ(atmp.A+1); a.B.B = DB #define O_dxx(a) a.A = (M_READ(PC.W++) + D.W + X.W); a.B.B = 0; \ if (F_getE) a.B.H = 0 #define O_dxy(a) a.A = (M_READ(PC.W++) + D.W + Y.W); a.B.B = 0; \ if (F_getE) a.B.H = 0 #define O_axx(a) a.B.L = M_READ(PC.W++); a.B.H = M_READ(PC.W++); a.B.B = DB; a.A += X.W; \ if (F_getE) a.B.B = 0 #define O_axy(a) a.B.L = M_READ(PC.W++); a.B.H = M_READ(PC.W++); a.B.B = DB; a.A += Y.W; \ if (F_getE) a.B.B = 0 #define O_alxx(a) a.B.L = M_READ(PC.W++); a.B.H = M_READ(PC.W++); a.B.B = M_READ(PC.W++); a.A += X.W #define O_pcr(a) atmp.B.L = M_READ(PC.W++); \ a.A = PC.W + (offset_s) atmp.B.L; a.B.B = PB; #define O_pcrl(a) wtmp.B.L = M_READ(PC.W++); wtmp.B.H = M_READ(PC.W++); \ a.A = PC.W + (offset_l) wtmp.W; a.B.B = PB; #define O_ai(a) atmp.B.L = M_READ(PC.W++); atmp.B.H = M_READ(PC.W++); atmp.B.B = 0; \ a.B.L = M_READ(atmp.A); a.B.H = M_READ(atmp.A+1); a.B.B = 0 #define O_ail(a) atmp.B.L = M_READ(PC.W++); atmp.B.H = M_READ(PC.W++); atmp.B.B = 0; \ a.B.L = M_READ(atmp.A); a.B.H = M_READ(atmp.A+1); a.B.B = M_READ(atmp.A+2) #define O_di(a) atmp.A = M_READ(PC.W++) + D.W; \ a.B.L = M_READ(atmp.A); a.B.H = M_READ(atmp.A+1); a.B.B = DB #define O_dil(a) atmp.A = M_READ(PC.W++) + D.W; \ a.B.L = M_READ(atmp.A); a.B.H = M_READ(atmp.A+1); a.B.B = M_READ(atmp.A+2) #define O_axi(a) atmp.B.L = M_READ(PC.W++); atmp.B.H = M_READ(PC.W++); atmp.A += X.W; atmp.B.B = 0; \ a.B.L = M_READ(atmp.A); a.B.H = M_READ(atmp.A+1); a.B.B = 0 #define O_sr(a) a.A = (M_READ(PC.W++) + S.W) & 0xFFFF; #define O_srix(a) atmp.A = (M_READ(PC.W++) + S.W) & 0xFFFF; \ a.B.L = M_READ(atmp.A); a.B.H = M_READ(atmp.A+1); a.B.B = DB; a.A += Y.W