From a2009261c03a4935ab34a832669c7759eac583f9 Mon Sep 17 00:00:00 2001 From: mpohoreski Date: Wed, 19 May 2010 14:49:26 +0000 Subject: [PATCH] Split from cpu.cpp Added #undef to all instructions to allow multiple #including --- source/CPU/cpu_instructions.inl | 625 ++++++++++++++++++++++++++++++++ 1 file changed, 625 insertions(+) create mode 100644 source/CPU/cpu_instructions.inl diff --git a/source/CPU/cpu_instructions.inl b/source/CPU/cpu_instructions.inl new file mode 100644 index 00000000..ff511c74 --- /dev/null +++ b/source/CPU/cpu_instructions.inl @@ -0,0 +1,625 @@ +/* +AppleWin : An Apple //e emulator for Windows + +Copyright (C) 1994-1996, Michael O'Brien +Copyright (C) 1999-2001, Oliver Schmidt +Copyright (C) 2002-2005, Tom Charlesworth +Copyright (C) 2006-2010, Tom Charlesworth, Michael Pohoreski + +AppleWin 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. + +AppleWin 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 AppleWin; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Description: 6502/65C02 emulation + * + * Author: Various + */ + +// TO DO: +// . All these CPP macros need to be converted to inline funcs + +/**************************************************************************** +* +* INSTRUCTION MACROS +* +***/ + +#undef ADC_NMOS +#undef ADC_CMOS +#undef ALR +#undef AND +#undef ANC +#undef ARR +#undef ASL_NMOS +#undef ASL_CMOS +#undef ASLA +#undef ASO +#undef AXA +#undef AXS +#undef BCC +#undef BCS +#undef BEQ +#undef BIT +#undef BITI +#undef BMI +#undef BNE +#undef BPL +#undef BRA +#undef BRK +#undef BVC +#undef BVS +#undef CLC +#undef CLD +#undef CLI +#undef CLV +#undef CMP +#undef CPX +#undef CPY +#undef DCM +#undef DEA +#undef DEC_NMOS +#undef DEC_CMOS +#undef DEX +#undef DEY +#undef EOR +#undef HLT +#undef INA +#undef INC_NMOS +#undef INC_CMOS +#undef INS +#undef INX +#undef INY +#undef JMP +#undef JSR +#undef LAS +#undef LAX +#undef LDA +#undef LDX +#undef LDY +#undef LSE +#undef LSR_NMOS +#undef LSR_CMOS +#undef LSRA +#undef NOP +#undef OAL +#undef ORA +#undef PHA +#undef PHP +#undef PHX +#undef PHY +#undef PLA +#undef PLP +#undef PLX +#undef PLY +#undef RLA +#undef ROL_NMOS +#undef ROL_CMOS +#undef ROLA +#undef ROR_NMOS +#undef ROR_CMOS +#undef RORA +#undef RRA +#undef RTI +#undef RTS +#undef SAX +#undef SAY +#undef SBC_NMOS +#undef SBC_CMOS +#undef SEC +#undef SED +#undef SEI +#undef STA +#undef STX +#undef STY +#undef STZ +#undef TAS +#undef TAX +#undef TAY +#undef TRB +#undef TSB +#undef TSX +#undef TXA +#undef TXS +#undef TYA +#undef XAA +#undef XAS + +// ========== + +#define ADC_NMOS bSlowerOnPagecross = 1; \ + temp = READ; \ + if (regs.ps & AF_DECIMAL) { \ + val = (regs.a & 0x0F) + (temp & 0x0F) + flagc; \ + if (val > 0x09) \ + val += 0x06; \ + if (val <= 0x0F) \ + val = (val & 0x0F) + (regs.a & 0xF0) + (temp & 0xF0); \ + else \ + val = (val & 0x0F) + (regs.a & 0xF0) + (temp & 0xF0) + 0x10;\ + flagz = !((regs.a + temp + flagc) & 0xFF); \ + flagn = (val & 0x80); \ + flagv = ((regs.a ^ val) & 0x80) && !((regs.a ^ temp) & 0x80);\ + if ((val & 0x1F0) > 0x90) \ + val += 0x60; \ + flagc = ((val & 0xFF0) > 0xF0); \ + regs.a = val & 0xFF; \ + } \ + else { \ + val = regs.a + temp + flagc; \ + flagc = (val > 0xFF); \ + flagv = (((regs.a & 0x80) == (temp & 0x80)) && \ + ((regs.a & 0x80) != (val & 0x80))); \ + regs.a = val & 0xFF; \ + SETNZ(regs.a); \ + } +#define ADC_CMOS bSlowerOnPagecross = 1; \ + temp = READ; \ + flagv = !((regs.a ^ temp) & 0x80); \ + if (regs.ps & AF_DECIMAL) { \ + uExtraCycles++; \ + val = (regs.a & 0x0f) + (temp & 0x0f) + flagc; \ + if (val >= 0x0A) \ + val = 0x10 | ((val + 6) & 0x0f); \ + val += (regs.a & 0xf0) + (temp & 0xf0); \ + if (val >= 0xA0) { \ + flagc = 1; \ + if (val >= 0x180) \ + flagv = 0; \ + val += 0x60; \ + } \ + else { \ + flagc = 0; \ + if (val < 0x80) \ + flagv = 0; \ + } \ + } \ + else { \ + val = regs.a + temp + flagc; \ + if (val >= 0x100) { \ + flagc = 1; \ + if (val >= 0x180) flagv = 0; \ + } \ + else { \ + flagc = 0; \ + if (val < 0x80) flagv = 0; \ + } \ + } \ + regs.a = val & 0xFF; \ + SETNZ(regs.a) +#define ALR regs.a &= READ; \ + flagc = (regs.a & 1); \ + flagn = 0; \ + regs.a >>= 1; \ + SETZ(regs.a) +#define AND bSlowerOnPagecross = 1; \ + regs.a &= READ; \ + SETNZ(regs.a) +#define ANC regs.a &= READ; \ + SETNZ(regs.a) \ + flagc = !!flagn; +#define ARR temp = regs.a & READ; /* Yes, this is sick */ \ + if (regs.ps & AF_DECIMAL) { \ + val = temp; \ + val |= (flagc ? 0x100 : 0); \ + val >>= 1; \ + flagn = (flagc ? 0x80 : 0); \ + SETZ(val) \ + flagv = ((val ^ temp) & 0x40); \ + if (((val & 0x0F) + (val & 0x01)) > 0x05) \ + val = (val & 0xF0) | ((val + 0x06) & 0x0F); \ + if (((val & 0xF0) + (val & 0x10)) > 0x50) { \ + val = (val & 0x0F) | ((val + 0x60) & 0xF0); \ + flagc = 1; \ + } \ + else \ + flagc = 0; \ + regs.a = (val & 0xFF); \ + } \ + else { \ + val = temp | (flagc ? 0x100 : 0); \ + val >>= 1; \ + SETNZ(val) \ + flagc = !!(val & 0x40); \ + flagv = ((val & 0x40) ^ ((val & 0x20) << 1)); \ + regs.a = (val & 0xFF); \ + } +#define ASL_NMOS bSlowerOnPagecross = 0; \ + val = READ << 1; \ + flagc = (val > 0xFF); \ + SETNZ(val) \ + WRITE(val) +#define ASL_CMOS bSlowerOnPagecross = 1; \ + val = READ << 1; \ + flagc = (val > 0xFF); \ + SETNZ(val) \ + WRITE(val) +#define ASLA val = regs.a << 1; \ + flagc = (val > 0xFF); \ + SETNZ(val) \ + regs.a = (BYTE)val; +#define ASO bSlowerOnPagecross = 0; \ + val = READ << 1; \ + flagc = (val > 0xFF); \ + WRITE(val) \ + regs.a |= val; \ + SETNZ(regs.a) +#define AXA bSlowerOnPagecross = 0;/*FIXME: $93 case is still unclear*/ \ + val = regs.a & regs.x & (((base >> 8) + 1) & 0xFF); \ + WRITE(val) +#define AXS bSlowerOnPagecross = 0; \ + WRITE(regs.a & regs.x) +#define BCC if (!flagc) BRANCH_TAKEN; +#define BCS if ( flagc) BRANCH_TAKEN; +#define BEQ if ( flagz) BRANCH_TAKEN; +#define BIT bSlowerOnPagecross = 1; \ + val = READ; \ + flagz = !(regs.a & val); \ + flagn = val & 0x80; \ + flagv = val & 0x40; +#define BITI flagz = !(regs.a & READ); +#define BMI if ( flagn) BRANCH_TAKEN; +#define BNE if (!flagz) BRANCH_TAKEN; +#define BPL if (!flagn) BRANCH_TAKEN; +#define BRA BRANCH_TAKEN; +#define BRK regs.pc++; \ + PUSH(regs.pc >> 8) \ + PUSH(regs.pc & 0xFF) \ + EF_TO_AF \ + PUSH(regs.ps); \ + regs.ps |= AF_INTERRUPT; \ + regs.pc = *(LPWORD)(mem+0xFFFE); +#define BVC if (!flagv) BRANCH_TAKEN; +#define BVS if ( flagv) BRANCH_TAKEN; +#define CLC flagc = 0; +#define CLD regs.ps &= ~AF_DECIMAL; +#define CLI regs.ps &= ~AF_INTERRUPT; +#define CLV flagv = 0; +#define CMP bSlowerOnPagecross = 1; \ + val = READ; \ + flagc = (regs.a >= val); \ + val = regs.a-val; \ + SETNZ(val) +#define CPX val = READ; \ + flagc = (regs.x >= val); \ + val = regs.x-val; \ + SETNZ(val) +#define CPY val = READ; \ + flagc = (regs.y >= val); \ + val = regs.y-val; \ + SETNZ(val) +#define DCM bSlowerOnPagecross = 0; \ + val = READ-1; \ + WRITE(val) \ + flagc = (regs.a >= val); \ + val = regs.a-val; \ + SETNZ(val) +#define DEA --regs.a; \ + SETNZ(regs.a) +#define DEC_NMOS bSlowerOnPagecross = 0; \ + val = READ-1; \ + SETNZ(val) \ + WRITE(val) +#define DEC_CMOS bSlowerOnPagecross = 1; \ + val = READ-1; \ + SETNZ(val) \ + WRITE(val) +#define DEX --regs.x; \ + SETNZ(regs.x) +#define DEY --regs.y; \ + SETNZ(regs.y) +#define EOR bSlowerOnPagecross = 1; \ + regs.a ^= READ; \ + SETNZ(regs.a) +#define HLT regs.bJammed = 1; \ + --regs.pc; +#define INA ++regs.a; \ + SETNZ(regs.a) +#define INC_NMOS bSlowerOnPagecross = 0; \ + val = READ+1; \ + SETNZ(val) \ + WRITE(val) +#define INC_CMOS bSlowerOnPagecross = 1; \ + val = READ+1; \ + SETNZ(val) \ + WRITE(val) +#define INS bSlowerOnPagecross = 0; \ + val = READ+1; \ + WRITE(val) \ + temp = val; \ + temp2 = regs.a - temp - !flagc; \ + if (regs.ps & AF_DECIMAL) { \ + val = (regs.a & 0x0F) - (temp & 0x0F) - !flagc; \ + if (val & 0x10) \ + val = ((val - 0x06) & 0x0F) | ((regs.a & 0xF0) - (temp & 0xF0) - 0x10);\ + else \ + val = (val & 0x0F) | ((regs.a & 0xF0) - (temp & 0xF0));\ + if (val & 0x100) \ + val -= 0x60; \ + flagc = (temp2 < 0x100); \ + SETNZ(temp2 & 0xFF); \ + flagv = ((regs.a ^ temp2) & 0x80) && ((regs.a ^ temp) & 0x80);\ + regs.a = val & 0xFF; \ + } \ + else { \ + val = temp2; \ + flagc = (val < 0x100); \ + flagv = (((regs.a & 0x80) != (temp & 0x80)) && \ + ((regs.a & 0x80) != (val & 0x80))); \ + regs.a = val & 0xFF; \ + SETNZ(regs.a); \ + } +#define INX ++regs.x; \ + SETNZ(regs.x) +#define INY ++regs.y; \ + SETNZ(regs.y) +#define JMP regs.pc = addr; +#define JSR --regs.pc; \ + PUSH(regs.pc >> 8) \ + PUSH(regs.pc & 0xFF) \ + regs.pc = addr; +#define LAS bSlowerOnPagecross = 1; \ + val = (BYTE)(READ & regs.sp); \ + regs.a = regs.x = (BYTE) val; \ + regs.sp = val | 0x100; \ + SETNZ(val) +#define LAX bSlowerOnPagecross = 1; \ + regs.a = regs.x = READ; \ + SETNZ(regs.a) +#define LDA bSlowerOnPagecross = 1; \ + regs.a = READ; \ + SETNZ(regs.a) +#define LDX bSlowerOnPagecross = 1; \ + regs.x = READ; \ + SETNZ(regs.x) +#define LDY bSlowerOnPagecross = 1; \ + regs.y = READ; \ + SETNZ(regs.y) +#define LSE bSlowerOnPagecross = 0; \ + val = READ; \ + flagc = (val & 1); \ + val >>= 1; \ + WRITE(val) \ + regs.a ^= val; \ + SETNZ(regs.a) +#define LSR_NMOS bSlowerOnPagecross = 0; \ + val = READ; \ + flagc = (val & 1); \ + flagn = 0; \ + val >>= 1; \ + SETZ(val) \ + WRITE(val) +#define LSR_CMOS bSlowerOnPagecross = 1; \ + val = READ; \ + flagc = (val & 1); \ + flagn = 0; \ + val >>= 1; \ + SETZ(val) \ + WRITE(val) +#define LSRA flagc = (regs.a & 1); \ + flagn = 0; \ + regs.a >>= 1; \ + SETZ(regs.a) +#define NOP bSlowerOnPagecross = 1; +#define OAL regs.a |= 0xEE; \ + regs.a &= READ; \ + regs.x = regs.a; \ + SETNZ(regs.a) +#define ORA bSlowerOnPagecross = 1; \ + regs.a |= READ; \ + SETNZ(regs.a) +#define PHA PUSH(regs.a) +#define PHP EF_TO_AF \ + PUSH(regs.ps) +#define PHX PUSH(regs.x) +#define PHY PUSH(regs.y) +#define PLA regs.a = POP; \ + SETNZ(regs.a) +#define PLP regs.ps = POP | AF_RESERVED | AF_BREAK; \ + AF_TO_EF +#define PLX regs.x = POP; \ + SETNZ(regs.x) +#define PLY regs.y = POP; \ + SETNZ(regs.y) +#define RLA bSlowerOnPagecross = 0; \ + val = (READ << 1) | flagc; \ + flagc = (val > 0xFF); \ + WRITE(val) \ + regs.a &= val; \ + SETNZ(regs.a) +#define ROL_NMOS bSlowerOnPagecross = 0; \ + val = (READ << 1) | flagc; \ + flagc = (val > 0xFF); \ + SETNZ(val) \ + WRITE(val) +#define ROL_CMOS bSlowerOnPagecross = 1; \ + val = (READ << 1) | flagc; \ + flagc = (val > 0xFF); \ + SETNZ(val) \ + WRITE(val) +#define ROLA val = (((WORD)regs.a) << 1) | flagc; \ + flagc = (val > 0xFF); \ + regs.a = val & 0xFF; \ + SETNZ(regs.a); +#define ROR_NMOS bSlowerOnPagecross = 0; \ + temp = READ; \ + val = (temp >> 1) | (flagc ? 0x80 : 0); \ + flagc = (temp & 1); \ + SETNZ(val) \ + WRITE(val) +#define ROR_CMOS bSlowerOnPagecross = 1; \ + temp = READ; \ + val = (temp >> 1) | (flagc ? 0x80 : 0); \ + flagc = (temp & 1); \ + SETNZ(val) \ + WRITE(val) +#define RORA val = (((WORD)regs.a) >> 1) | (flagc ? 0x80 : 0); \ + flagc = (regs.a & 1); \ + regs.a = val & 0xFF; \ + SETNZ(regs.a) +#define RRA bSlowerOnPagecross = 0; \ + temp = READ; \ + val = (temp >> 1) | (flagc ? 0x80 : 0); \ + flagc = (temp & 1); \ + WRITE(val) \ + temp = val; \ + if (regs.ps & AF_DECIMAL) { \ + val = (regs.a & 0x0F) + (temp & 0x0F) + flagc; \ + if (val > 0x09) \ + val += 0x06; \ + if (val <= 0x0F) \ + val = (val & 0x0F) + (regs.a & 0xF0) + (temp & 0xF0); \ + else \ + val = (val & 0x0F) + (regs.a & 0xF0) + (temp & 0xF0) + 0x10;\ + flagz = !((regs.a + temp + flagc) & 0xFF); \ + flagn = (val & 0x80); \ + flagv = ((regs.a ^ val) & 0x80) && !((regs.a ^ temp) & 0x80);\ + if ((val & 0x1F0) > 0x90) \ + val += 0x60; \ + flagc = ((val & 0xFF0) > 0xF0); \ + regs.a = val & 0xFF; \ + } \ + else { \ + val = regs.a + temp + flagc; \ + flagc = (val > 0xFF); \ + flagv = (((regs.a & 0x80) == (temp & 0x80)) && \ + ((regs.a & 0x80) != (val & 0x80))); \ + regs.a = val & 0xFF; \ + SETNZ(regs.a); \ + } +#define RTI regs.ps = POP | AF_RESERVED | AF_BREAK; \ + AF_TO_EF \ + regs.pc = POP; \ + regs.pc |= (((WORD)POP) << 8); +#define RTS regs.pc = POP; \ + regs.pc |= (((WORD)POP) << 8); \ + ++regs.pc; +#define SAX temp = regs.a & regs.x; \ + val = READ; \ + flagc = (temp >= val); \ + regs.x = temp-val; \ + SETNZ(regs.x) +#define SAY bSlowerOnPagecross = 0; \ + val = regs.y & (((base >> 8) + 1) & 0xFF); \ + WRITE(val) +#define SBC_NMOS bSlowerOnPagecross = 1; \ + temp = READ; \ + temp2 = regs.a - temp - !flagc; \ + if (regs.ps & AF_DECIMAL) { \ + val = (regs.a & 0x0F) - (temp & 0x0F) - !flagc; \ + if (val & 0x10) \ + val = ((val - 0x06) & 0x0F) | ((regs.a & 0xF0) - (temp & 0xF0) - 0x10);\ + else \ + val = (val & 0x0F) | ((regs.a & 0xF0) - (temp & 0xF0));\ + if (val & 0x100) \ + val -= 0x60; \ + flagc = (temp2 < 0x100); \ + SETNZ(temp2 & 0xFF); \ + flagv = ((regs.a ^ temp2) & 0x80) && ((regs.a ^ temp) & 0x80);\ + regs.a = val & 0xFF; \ + } \ + else { \ + val = temp2; \ + flagc = (val < 0x100); \ + flagv = (((regs.a & 0x80) != (temp & 0x80)) && \ + ((regs.a & 0x80) != (val & 0x80))); \ + regs.a = val & 0xFF; \ + SETNZ(regs.a); \ + } +#define SBC_CMOS bSlowerOnPagecross = 1; \ + temp = READ; \ + flagv = ((regs.a ^ temp) & 0x80); \ + if (regs.ps & AF_DECIMAL) { \ + uExtraCycles++; \ + temp2 = 0x0F + (regs.a & 0x0F) - (temp & 0x0F) + flagc; \ + if (temp2 < 0x10) { \ + val = 0; \ + temp2 -= 0x06; \ + } \ + else { \ + val = 0x10; \ + temp2 -= 0x10; \ + } \ + val += 0xF0 + (regs.a & 0xF0) - (temp & 0xF0); \ + if (val < 0x100) { \ + flagc = 0; \ + if (val < 0x80) \ + flagv = 0; \ + val -= 0x60; \ + } \ + else { \ + flagc = 1; \ + if (val >= 0x180) \ + flagv = 0; \ + } \ + val += temp2; \ + } \ + else { \ + val = 0xff + regs.a - temp + flagc; \ + if (val < 0x100) { \ + flagc = 0; \ + if (val < 0x80) \ + flagv = 0; \ + } \ + else { \ + flagc = 1; \ + if (val >= 0x180) \ + flagv = 0; \ + } \ + } \ + regs.a = val & 0xFF; \ + SETNZ(regs.a) +#define SEC flagc = 1; +#define SED regs.ps |= AF_DECIMAL; +#define SEI regs.ps |= AF_INTERRUPT; +#define STA bSlowerOnPagecross = 0; \ + WRITE(regs.a) +#define STX bSlowerOnPagecross = 0; \ + WRITE(regs.x) +#define STY bSlowerOnPagecross = 0; \ + WRITE(regs.y) +#define STZ bSlowerOnPagecross = 0; \ + WRITE(0) +#define TAS bSlowerOnPagecross = 0; \ + val = regs.a & regs.x; \ + regs.sp = 0x100 | val; \ + val &= (((base >> 8) + 1) & 0xFF); \ + WRITE(val) +#define TAX regs.x = regs.a; \ + SETNZ(regs.x) +#define TAY regs.y = regs.a; \ + SETNZ(regs.y) +#define TRB bSlowerOnPagecross = 0; \ + val = READ; \ + flagz = !(regs.a & val); \ + val &= ~regs.a; \ + WRITE(val) +#define TSB bSlowerOnPagecross = 0; \ + val = READ; \ + flagz = !(regs.a & val); \ + val |= regs.a; \ + WRITE(val) +#define TSX regs.x = regs.sp & 0xFF; \ + SETNZ(regs.x) +#define TXA regs.a = regs.x; \ + SETNZ(regs.a) +#define TXS regs.sp = 0x100 | regs.x; +#define TYA regs.a = regs.y; \ + SETNZ(regs.a) +#define XAA regs.a = regs.x; \ + regs.a &= READ; \ + SETNZ(regs.a) +#define XAS bSlowerOnPagecross = 0; \ + val = regs.x & (((base >> 8) + 1) & 0xFF); \ + WRITE(val) +