1 /***************************************************************************** 2 * 3 * opsce02.h 4 * Addressing mode and opcode macros for 65ce02 CPU 5 * 6 * Copyright (c) 2000 Peter Trauner, all rights reserved. 7 * documentation preliminary databook 8 * documentation by michael steil mist@c64.org 9 * available at ftp://ftp.funet.fi/pub/cbm/c65 10 * 11 * - This source code is released as freeware for non-commercial purposes. 12 * - You are free to use and redistribute this code in modified or 13 * unmodified form, provided you list me in the credits. 14 * - If you modify this source code, you must add a notice to each modified 15 * source file that it has been changed. If you're a nice person, you 16 * will clearly mark each change too. :) 17 * - If you wish to use this for commercial purposes, please contact me at 18 * pullmoll@t-online.de 19 * - The author of this copywritten work reserves the right to change the 20 * terms of its usage and license at any time, including retroactively 21 * - This entire notice must remain in the source code. 22 * 23 *****************************************************************************/ 24 25 #define m6502 m65ce02 26 #define m6502_ICount m65ce02_ICount 27 28 /* stack disable extended (word) mode */ 29 #undef F_T 30 #define F_E 0x20 31 32 /* some shortcuts for improved readability */ 33 #define Z m65ce02.z 34 #define B m65ce02.zp.b.h 35 #define SW m6502.sp.w.l 36 #define SPL m6502.sp.b.l 37 #define SPH m6502.sp.b.h 38 39 #define PEEK_OP() cpu_readop(PCW) 40 41 #define RDMEM_WORD(addr, pair) \ 42 pair.b.l=RDMEM( addr ); \ 43 pair.b.h=RDMEM( (addr+1) & 0xffff ) 44 45 #define WRMEM_WORD(addr,pair) \ 46 WRMEM(addr,pair.b.l); \ 47 WRMEM((addr+1)&0xffff,pair.b.h) 48 49 #define WB_EA_WORD WRMEM_WORD(EAD, tmp) 50 51 52 #define SET_NZ_WORD(n) \ 53 if( n.w.l == 0 ) \ 54 P = (P & ~F_N) | F_Z; \ 55 else \ 56 P = (P & ~(F_N | F_Z)) | ((n.b.h) & F_N) 57 58 /* EA_IDY 59 * ???? subtract 1 cycle if page boundary is crossed */ 60 61 62 /*************************************************************** 63 * EA = zero page indirect + Z (post indexed) 64 * ???? subtract 1 cycle if page boundary is crossed 65 ***************************************************************/ 66 #define EA_IDZ \ 67 ZPL = RDOPARG(); \ 68 EAL = RDMEM(ZPD); \ 69 ZPL++; \ 70 EAH = RDMEM(ZPD); \ 71 if (EAL + Z > 0xff) \ 72 m6502_ICount--; \ 73 EAW += Z 74 75 /*************************************************************** 76 * EA = zero page indexed stack, indirect + Y (post indexed) 77 * ??? subtract 1 cycle if page boundary is crossed 78 ***************************************************************/ 79 /* i think its based on stack high byte instead of of bank register */ 80 #define EA_ZP_INSP_INY \ 81 { \ 82 PAIR pair={{0}}; \ 83 pair.b.l = SPL+RDOPARG(); \ 84 pair.b.h = SPH; \ 85 EAL = RDMEM(pair.d); \ 86 if( P & F_E ) \ 87 pair.b.l++; \ 88 else \ 89 pair.w.l++; \ 90 EAH = RDMEM(pair.d); \ 91 if( EAL + Y > 0xff ) \ 92 m6502_ICount--; \ 93 EAW += Y; \ 94 } 95 96 #define RD_IMM_WORD tmp.b.l = RDOPARG(); tmp.b.h=RDOPARG() 97 #define RD_IDZ EA_IDZ; tmp = RDMEM(EAD) 98 #define WR_IDZ EA_IDZ; WRMEM(EAD, tmp) 99 100 #define RD_INSY EA_ZP_INSP_INY; tmp = RDMEM(EAD) 101 #define WR_INSY EA_ZP_INSP_INY; WRMEM(EAD, tmp) 102 103 #define RD_ABS_WORD EA_ABS; RDMEM_WORD(EAD, tmp) 104 #define WR_ABS_WORD EA_ABS; WRMEM_WORD(EAD, tmp) 105 106 #define RD_ZPG_WORD EA_ZPG; RDMEM_WORD(EAD, tmp) 107 #define WR_ZPG_WORD EA_ZPG; WRMEM_WORD(EAD, tmp) 108 109 /*************************************************************** 110 * push a register onto the stack 111 ***************************************************************/ 112 #undef PUSH 113 #define PUSH(Rg) WRMEM(SPD, Rg); if (P&F_E) { S--; } else { SW--; } 114 115 /*************************************************************** 116 * pull a register from the stack 117 ***************************************************************/ 118 #undef PULL 119 #define PULL(Rg) if (P&F_E) { S++; } else { SW++; } Rg = RDMEM(SPD) 120 121 /* the order in which the args are pushed is correct! */ 122 #define PUSH_WORD(pair) PUSH(pair.b.l);PUSH(pair.b.h) 123 124 /*************************************************************** 125 * BRA branch relative 126 * extra cycle if page boundary is crossed 127 ***************************************************************/ 128 #undef BRA 129 #define BRA(cond) \ 130 if (cond) \ 131 { \ 132 tmp = RDOPARG(); \ 133 EAW = PCW + (signed char)tmp; \ 134 PCD = EAD; \ 135 CHANGE_PC; \ 136 } \ 137 else \ 138 { \ 139 PCW++; \ 140 } 141 142 /*************************************************************** 143 * BRA branch relative 144 ***************************************************************/ 145 #define BRA_WORD(cond) \ 146 if (cond) \ 147 { \ 148 EAL = RDOPARG(); \ 149 EAH = RDOPARG(); \ 150 EAW = PCW + (short)(EAW-1); \ 151 PCD = EAD; \ 152 CHANGE_PC; \ 153 } \ 154 else \ 155 { \ 156 PCW += 2; \ 157 } 158 159 /* 65ce02 ****************************************************** 160 * cle clear disable extended stack flag 161 ***************************************************************/ 162 #define CLE \ 163 P|=F_E 164 165 /* 65ce02 ****************************************************** 166 * see set disable extended stack flag 167 ***************************************************************/ 168 #define SEE \ 169 P&=~F_E 170 171 /* 65ce02 ****************************************************** 172 * augment 173 ***************************************************************/ 174 #define AUG \ 175 t1=RDOPARG(); t2=RDOPARG(); t3=RDOPARG(); \ 176 logerror("m65ce02 at pc:%.4x reserved op aug %.2x %.2x %.2x\n", \ 177 t1,t2,t3); 178 179 /* 65ce02 ****************************************************** 180 * rts imm 181 ***************************************************************/ 182 #define RTN \ 183 if (P&F_E) { S+=tmp; } else { SW+=tmp; } 184 185 /* 65ce02 ****************************************************** 186 * NEG accu 187 * twos complement 188 ***************************************************************/ 189 #define NEG \ 190 A= (A^0xff)+1; \ 191 SET_NZ(A) 192 193 /* 65ce02 ****************************************************** 194 * ASR arithmetic (signed) shift right 195 * [7] -> [7][6][5][4][3][2][1][0] -> C 196 ***************************************************************/ 197 #define ASR_65CE02 \ 198 P = (P & ~F_C) | (tmp & F_C); \ 199 tmp = (signed char)tmp >> 1; \ 200 SET_NZ(tmp) 201 202 /* 65ce02 ****************************************************** 203 * ASW arithmetic shift left word 204 * [c] <- [15]..[6][5][4][3][2][1][0] 205 ***************************************************************/ 206 /* not sure about how 16 bit memory modifying is executed */ 207 #define ASW \ 208 tmp.w.l = tmp.w.l << 1; \ 209 P = (P & ~F_C) | (tmp.b.h2 & F_C); \ 210 SET_NZ_WORD(tmp); 211 212 /* 65ce02 ****************************************************** 213 * ROW rotate left word 214 * [c] <- [15]..[6][5][4][3][2][1][0] <- C 215 ***************************************************************/ 216 /* not sure about how 16 bit memory modifying is executed */ 217 #define ROW \ 218 tmp.d =(tmp.d << 1); \ 219 tmp.w.l |= (P & F_C); \ 220 P = (P & ~F_C) | (tmp.w.l & F_C); \ 221 SET_NZ_WORD(tmp); \ 222 223 /* 65ce02 ****************************************************** 224 * CPZ Compare index Z 225 ***************************************************************/ 226 #define CPZ \ 227 P &= ~F_C; \ 228 if (Z >= tmp) \ 229 P |= F_C; \ 230 SET_NZ((UINT8)(Z - tmp)) 231 232 /* 65ce02 ****************************************************** 233 * DEZ Decrement index Z 234 ***************************************************************/ 235 #define DEZ \ 236 Z = (UINT8)--Z; \ 237 SET_NZ(Z) 238 239 /* 65ce02 ****************************************************** 240 * DEC Decrement memory word 241 ***************************************************************/ 242 /* not sure about this */ 243 #define DEW \ 244 tmp.w.l = --tmp.w.l; \ 245 SET_NZ_WORD(tmp) 246 247 /* 65ce02 ****************************************************** 248 * DEZ Decrement index Z 249 ***************************************************************/ 250 #define INZ \ 251 Z = (UINT8)++Z; \ 252 SET_NZ(Z) 253 254 /* 65ce02 ****************************************************** 255 * INW Increment memory word 256 ***************************************************************/ 257 #define INW \ 258 tmp.w.l = ++tmp.w.l; \ 259 SET_NZ_WORD(tmp) 260 261 /* 65ce02 ****************************************************** 262 * LDZ Load index Z 263 ***************************************************************/ 264 #define LDZ \ 265 Z = (UINT8)tmp; \ 266 SET_NZ(Z) 267 268 /* 65ce02 ****************************************************** 269 * STZ Store index Z 270 ***************************************************************/ 271 #define STZ_65CE02 \ 272 tmp = Z 273 274 /* 65ce02 ****************************************************** 275 * PHZ Push index z 276 ***************************************************************/ 277 #define PHZ \ 278 PUSH(Z) 279 280 /* 65ce02 ****************************************************** 281 * PLA Pull accumulator 282 ***************************************************************/ 283 #define PLZ \ 284 PULL(Z); \ 285 SET_NZ(Z) 286 287 /* 65ce02 ****************************************************** 288 * TAZ Transfer accumulator to index z 289 ***************************************************************/ 290 #define TAZ \ 291 Z = A; \ 292 SET_NZ(Z) 293 294 /* 65ce02 ****************************************************** 295 * TZA Transfer index z to accumulator 296 ***************************************************************/ 297 #define TZA \ 298 A = Z; \ 299 SET_NZ(A) 300 301 /* 65ce02 ****************************************************** 302 * TSY Transfer stack pointer to index y 303 ***************************************************************/ 304 #define TSY \ 305 Y = SPH; \ 306 SET_NZ(Y) 307 308 /* 65ce02 ****************************************************** 309 * TYS Transfer index y to stack pointer 310 ***************************************************************/ 311 #define TYS \ 312 SPH = Y; 313 314 /* 65ce02 ****************************************************** 315 * TAB Transfer accumulator to Direct Page 316 ***************************************************************/ 317 #define TAB \ 318 B = A; \ 319 SET_NZ(B) 320 321 /* 65ce02 ****************************************************** 322 * TBA Transfer direct page to accumulator 323 ***************************************************************/ 324 #define TBA \ 325 A = B; \ 326 SET_NZ(A) 327 328 /* 65ce02 ****************************************************** 329 * BCC Branch if carry clear 330 ***************************************************************/ 331 #define BCC_WORD BRA_WORD(!(P & F_C)) 332 333 /* 65ce02 ****************************************************** 334 * BCS Branch if carry set 335 ***************************************************************/ 336 #define BCS_WORD BRA_WORD(P & F_C) 337 338 /* 65ce02 ****************************************************** 339 * BEQ Branch if equal 340 ***************************************************************/ 341 #define BEQ_WORD BRA_WORD(P & F_Z) 342 343 /* 65ce02 ****************************************************** 344 * BMI Branch if minus 345 ***************************************************************/ 346 #define BMI_WORD BRA_WORD(P & F_N) 347 348 /* 65ce02 ****************************************************** 349 * BNE Branch if not equal 350 ***************************************************************/ 351 #define BNE_WORD BRA_WORD(!(P & F_Z)) 352 353 /* 65ce02 ****************************************************** 354 * BPL Branch if plus 355 ***************************************************************/ 356 #define BPL_WORD BRA_WORD(!(P & F_N)) 357 358 /* 65ce02 ****************************************************** 359 * BVC Branch if overflow clear 360 ***************************************************************/ 361 #define BVC_WORD BRA_WORD(!(P & F_V)) 362 363 /* 65ce02 ****************************************************** 364 * BVS Branch if overflow set 365 ***************************************************************/ 366 #define BVS_WORD BRA_WORD(P & F_V) 367 368 /* 65ce02 ****************************************************** 369 * JSR Jump to subroutine 370 * decrement PC (sic!) push PC hi, push PC lo and set 371 * PC to the effective address 372 ***************************************************************/ 373 #define JSR_IND \ 374 EAL = RDOPARG(); \ 375 PUSH(PCH); \ 376 PUSH(PCL); \ 377 EAH = RDOPARG(); \ 378 PCL = RDMEM(EAD); \ 379 EAL++; /* booby trap: stay in same page! ;-) */ \ 380 PCH = RDMEM(EAD); \ 381 CHANGE_PC 382 383 /* 65ce02 ****************************************************** 384 * JSR Jump to subroutine 385 * decrement PC (sic!) push PC hi, push PC lo and set 386 * PC to the effective address 387 ***************************************************************/ 388 #define JSR_INDX \ 389 EAL = RDOPARG()+X; \ 390 PUSH(PCH); \ 391 PUSH(PCL); \ 392 EAH = RDOPARG(); \ 393 PCL = RDMEM(EAD); \ 394 EAL++; /* booby trap: stay in same page! ;-) */ \ 395 PCH = RDMEM(EAD); \ 396 CHANGE_PC 397 398 /* 65ce02 ****************************************************** 399 * PLP Pull processor status (flags) 400 ***************************************************************/ 401 #undef PLP 402 #define PLP \ 403 if ( P & F_I ) \ 404 { \ 405 UINT8 temp; \ 406 PULL(temp); \ 407 P=(P&F_E)|F_B|(temp&~F_E); \ 408 if( m6502.irq_state != CLEAR_LINE && !(P & F_I) ) \ 409 { \ 410 LOG(("M65ce02#%d PLP sets after_cli\n", \ 411 cpu_getactivecpu())); \ 412 m6502.after_cli = 1; \ 413 } \ 414 } \ 415 else \ 416 { \ 417 UINT8 temp; \ 418 PULL(temp); \ 419 P=(P&F_E)|F_B|(temp&~F_E); \ 420 } 421 422 /* 65ce02 ******************************************************** 423 * RTI Return from interrupt 424 * pull flags, pull PC lo, pull PC hi and increment PC 425 * PCW++; 426 ***************************************************************/ 427 #undef RTI 428 #define RTI \ 429 { UINT8 temp;PULL(temp);P=(P&F_E)|F_B|(temp&~F_E); } \ 430 PULL(PCL); \ 431 PULL(PCH); \ 432 if( m65ce02.irq_state != CLEAR_LINE && !(P & F_I) ) \ 433 { \ 434 LOG(("M65ce02#%d RTI sets after_cli\n", \ 435 cpu_getactivecpu())); \ 436 m6502.after_cli = 1; \ 437 } \ 438 CHANGE_PC 439 440 /* 65ce02 ******************************************************** 441 * TXS Transfer index X to stack LSB 442 * no flags changed (sic!) 443 * txs tys not interruptable 444 ***************************************************************/ 445 #undef TXS 446 #define TXS \ 447 S = X; \ 448 if (PEEK_OP() == 0x2b /*TYS*/ ) \ 449 { \ 450 UINT8 op = RDOP(); \ 451 (*m65ce02.insn[op])(); \ 452 } 453