/ MCUME_teensy / teensy64 / cpu.cpp
cpu.cpp
   1  /*
   2      Copyright Mike Chambers, Frank Bösing, 2017
   3      Parts of this file are based on "Fake6502 CPU emulator core v1.1" by Mike Chambers
   4  
   5  
   6  	This file is part of Teensy64.
   7  
   8      Teensy64 is free software: you can redistribute it and/or modify
   9      it under the terms of the GNU General Public License as published by
  10      the Free Software Foundation, either version 3 of the License, or
  11      (at your option) any later version.
  12  
  13      Teensy64 is distributed in the hope that it will be useful,
  14      but WITHOUT ANY WARRANTY; without even the implied warranty of
  15      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16      GNU General Public License for more details.
  17  
  18      You should have received a copy of the GNU General Public License
  19      along with Teensy64.  If not, see <http://www.gnu.org/licenses/>.
  20  
  21      Diese Datei ist Teil von Teensy64.
  22  
  23      Teensy64 ist Freie Software: Sie können es unter den Bedingungen
  24      der GNU General Public License, wie von der Free Software Foundation,
  25      Version 3 der Lizenz oder (nach Ihrer Wahl) jeder späteren
  26      veröffentlichten Version, weiterverbreiten und/oder modifizieren.
  27  
  28      Teensy64 wird in der Hoffnung, dass es nützlich sein wird, aber
  29      OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
  30      Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
  31      Siehe die GNU General Public License für weitere Details.
  32  
  33      Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
  34      Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>.
  35  
  36  */
  37  
  38  /* Fake6502 CPU emulator core v1.1 *******************
  39   * (c)2011 Mike Chambers (miker00lz@gmail.com)       *
  40   *****************************************************
  41   * LICENSE: This source code is released into the    *
  42   * public domain, but if you use it please do give   *
  43   * credit. I put a lot of effort into writing this!  *
  44   *                                                   *
  45   *****************************************************
  46  */
  47  
  48  #include "cpu.h"
  49  
  50  #define FLAG_CARRY     0x01
  51  #define FLAG_ZERO      0x02
  52  #define FLAG_INTERRUPT 0x04
  53  #define FLAG_DECIMAL   0x08
  54  #define FLAG_BREAK     0x10
  55  #define FLAG_CONSTANT  0x20
  56  #define FLAG_OVERFLOW  0x40
  57  #define FLAG_SIGN      0x80
  58  
  59  //flag modifier macros
  60  #define setcarry() cpu.cpustatus |= FLAG_CARRY
  61  #define clearcarry() cpu.cpustatus &= (~FLAG_CARRY)
  62  #define setzero() cpu.cpustatus |= FLAG_ZERO
  63  #define clearzero() cpu.cpustatus &= (~FLAG_ZERO)
  64  #define setinterrupt() cpu.cpustatus |= FLAG_INTERRUPT
  65  #define clearinterrupt() cpu.cpustatus &= (~FLAG_INTERRUPT)
  66  #define setdecimal() cpu.cpustatus |= FLAG_DECIMAL
  67  #define cleardecimal() cpu.cpustatus &= (~FLAG_DECIMAL)
  68  #define setoverflow() cpu.cpustatus |= FLAG_OVERFLOW
  69  #define clearoverflow() cpu.cpustatus &= (~FLAG_OVERFLOW)
  70  #define setsign() cpu.cpustatus |= FLAG_SIGN
  71  #define clearsign() cpu.cpustatus &= (~FLAG_SIGN)
  72  
  73  
  74  //flag calculation macros
  75  #define zerocalc(n) { if ((n) & 0x00FF) clearzero(); else setzero(); }
  76  //#define signcalc(n) { if ((n) & 0x0080) setsign(); else clearsign(); }
  77  #define signcalc(n) { cpu.cpustatus =( cpu.cpustatus & 0x7f) | (n & 0x80); }
  78  #define carrycalc(n) { if ((n) & 0xFF00) setcarry(); else clearcarry(); }
  79  //#define carrycalc(n) {cpu.cpustatus =( cpu.cpustatus & 0xfe) | (n >> 8); }
  80  #define overflowcalc(n, m, o) { if (((n) ^ (uint16_t)(m)) & ((n) ^ (o)) & 0x0080) setoverflow(); else clearoverflow(); }
  81  
  82  #define saveaccum(n) cpu.a = (uint8_t)((n) & 0x00FF)
  83  
  84  #define UNSUPPORTED { printf("Unsupported Opcode\n"); while(1){;} }
  85  
  86  void logAddr(const uint32_t address, const uint8_t value, const uint8_t rw) {
  87  	if (rw) printf("Write "); else printf("Read ");
  88  	printf("0x%d=0x%d\n",address,value);
  89  
  90  }
  91  struct tcpu cpu;
  92  struct tio io;
  93  
  94  void reset6502();
  95  void cpu_nmi();
  96  static inline void cpu_irq();
  97  
  98  INLINEOP uint8_t read6502(const uint32_t address) __attribute__ ((hot));
  99  INLINEOP uint8_t read6502(const uint32_t address) {
 100  	return (*cpu.plamap_r)[address >> 8](address);
 101  }
 102  
 103  INLINEOP uint8_t read6502ZP(const uint32_t address) __attribute__ ((hot)); //Zeropage
 104  INLINEOP uint8_t read6502ZP(const uint32_t address) {
 105  	return cpu.RAM[address & 0xff];
 106  }
 107  
 108  /* Ein Schreibzugriff auf einen ROM-Bereich speichert das Byte im „darunterliegenden” RAM. */
 109  INLINEOP void write6502(const uint32_t address, const uint8_t value) __attribute__ ((hot));
 110  INLINEOP void write6502(const uint32_t address, const uint8_t value) {
 111   (*cpu.plamap_w)[address>>8](address, value);
 112  }
 113  
 114  //a few general functions used by various other functions
 115  INLINEOP void push16(const uint16_t pushval) {
 116      cpu.RAM[BASE_STACK + cpu.sp] = (pushval >> 8) & 0xFF;
 117      cpu.RAM[BASE_STACK + ((cpu.sp - 1) & 0xFF)] = pushval & 0xFF;
 118      cpu.sp -= 2;
 119  }
 120  
 121  INLINEOP uint16_t pull16() {
 122      uint16_t temp16;
 123      temp16 = cpu.RAM[BASE_STACK + ((cpu.sp + 1) & 0xFF)] | ((uint16_t)cpu.RAM[BASE_STACK + ((cpu.sp + 2) & 0xFF)] << 8);
 124      cpu.sp += 2;
 125      return(temp16);
 126  }
 127  
 128  INLINEOP void push8(uint8_t pushval) {
 129    cpu.RAM[BASE_STACK + (cpu.sp--)] = pushval;
 130  
 131  }
 132  
 133  INLINEOP uint8_t pull8() {
 134    return cpu.RAM[BASE_STACK + (++cpu.sp)];
 135  }
 136  
 137  /********************************************************************************************************************/
 138  /*addressing mode functions, calculates effective addresses                                                         */
 139  /********************************************************************************************************************/
 140  
 141  INLINEOP void imp() { //implied
 142  }
 143  
 144  INLINEOP void acc() { //accumulator
 145  }
 146  
 147  INLINEOP void imm() { //immediate
 148    cpu.ea = cpu.pc++;
 149  }
 150  
 151  INLINEOP void zp() { //zero-page
 152    cpu.ea = read6502(cpu.pc++) & 0xFF;
 153  }
 154  
 155  INLINEOP void zpx() { //zero-page,X
 156  	cpu.ea = (read6502(cpu.pc++) + cpu.x)  & 0xFF; //zero-page wraparound
 157  }
 158  
 159  INLINEOP void zpy() { //zero-page,Y
 160  	cpu.ea = (read6502(cpu.pc++) + cpu.y) & 0xFF; //zero-page wraparound
 161  }
 162  
 163  INLINEOP void rel() { //relative for branch ops (8-bit immediate value, sign-extended)
 164  	cpu.reladdr = read6502(cpu.pc++);
 165  	if (cpu.reladdr & 0x80) cpu.reladdr |= 0xFF00;
 166  }
 167  
 168  INLINEOP void abso() { //absolute
 169  	cpu.ea = read6502(cpu.pc) | (read6502(cpu.pc + 1) << 8);
 170  	cpu.pc += 2;
 171  }
 172  
 173  INLINEOP void absx() { //absolute,X
 174  	cpu.ea = (read6502(cpu.pc) | (read6502(cpu.pc + 1) << 8)) + cpu.x;
 175  	cpu.pc += 2;
 176  }
 177  
 178  INLINEOP void absx_t() { //absolute,X with extra cycle
 179  	uint16_t h = read6502(cpu.pc) + cpu.x;
 180  	if (h & 0x100) cpu.ticks += 1;
 181  	cpu.ea = h + (read6502(cpu.pc + 1) << 8);
 182  	cpu.pc += 2;
 183  }
 184  
 185  INLINEOP void absy() { //absolute,Y
 186  	cpu.ea = (read6502(cpu.pc) + (read6502(cpu.pc + 1) << 8)) + cpu.y;
 187  	cpu.pc += 2;
 188  }
 189  
 190  INLINEOP void absy_t() { //absolute,Y with extra cycle
 191  	uint16_t h = read6502(cpu.pc) + cpu.y;
 192  	if (h & 0x100) cpu.ticks += 1;
 193  	cpu.ea = h + (read6502(cpu.pc + 1) << 8);
 194  	cpu.pc += 2;
 195  }
 196  
 197  INLINEOP void ind() { //indirect
 198  	uint16_t eahelp, eahelp2;
 199  	eahelp = read6502(cpu.pc) | (read6502(cpu.pc + 1) << 8);
 200  	eahelp2 = (eahelp & 0xFF00) | ((eahelp + 1) & 0x00FF); //replicate 6502 page-boundary wraparound bug
 201  	cpu.ea = read6502(eahelp) | (read6502(eahelp2) << 8);
 202  	cpu.pc += 2;
 203  }
 204  
 205  INLINEOP void indx() { // (indirect,X)
 206  	uint32_t eahelp;
 207  	eahelp = (read6502(cpu.pc++) + cpu.x) & 0xFF; //zero-page wraparound for table pointer
 208  	cpu.ea = read6502ZP((uint8_t)eahelp) | (read6502ZP((uint8_t)(eahelp + 1)) << 8);
 209  }
 210  
 211  INLINEOP void indy() { // (zeropage indirect),Y
 212  	uint8_t zp = read6502(cpu.pc++);
 213  	cpu.ea = read6502ZP((uint16_t) zp++);
 214  	cpu.ea += (uint16_t) read6502ZP((uint16_t) zp) << 8;
 215  	cpu.ea += cpu.y;
 216  }
 217  
 218  INLINEOP void indy_t() { // (zeropage indirect),Y with extra cycle
 219  	uint8_t zp = read6502(cpu.pc++);
 220  	uint16_t h;
 221  	h = read6502ZP((uint16_t) zp++);
 222  	h += (uint16_t) read6502ZP((uint16_t) zp) << 8;
 223  	if (((h + cpu.y) & 0xff) != (h & 0xff)) cpu.ticks += 1;
 224  	cpu.ea = h + cpu.y;
 225  }
 226  
 227  INLINEOP uint32_t getvalue() __attribute__ ((hot));
 228  INLINEOP uint32_t getvalue() {
 229  	return read6502(cpu.ea);
 230  }
 231  
 232  INLINEOP uint32_t getvalueZP() __attribute__ ((hot));
 233  INLINEOP uint32_t getvalueZP() {
 234  	return read6502ZP(cpu.ea);
 235  }
 236  
 237  INLINEOP void putvalue(const uint8_t saveval)  __attribute__ ((hot));
 238  INLINEOP void putvalue(const uint8_t saveval) {
 239  	write6502(cpu.ea, saveval);
 240  }
 241  
 242  
 243  /********************************************************************************************************************/
 244  /* instruction handler functions                                          											*/
 245  /********************************************************************************************************************/
 246  
 247  /*
 248  Aliases used in other illegal opcode sources:
 249  
 250  SLO = ASO
 251  SRE = LSE
 252  ISC = ISB
 253  ALR = ASR
 254  SHX = A11 (A11 was a result of only having tested this one on adress $1000)
 255  SHY = A11
 256  LAS = LAR
 257  KIL = JAM, HLT
 258  */
 259  
 260  #define SETFLAGS(data)                  \
 261  {                                       \
 262    if (!(data))                          \
 263      cpu.cpustatus = (cpu.cpustatus & ~FLAG_SIGN) | FLAG_ZERO; \
 264    else                                  \
 265      cpu.cpustatus = (cpu.cpustatus & ~(FLAG_SIGN|FLAG_ZERO)) | \
 266      ((data) & FLAG_SIGN); \
 267  }
 268  
 269  
 270  INLINEOP void _adc(unsigned data) {
 271  	unsigned tempval = data;
 272  	unsigned temp;
 273      if (cpu.cpustatus & FLAG_DECIMAL) {
 274  	  	temp = (cpu.a & 0x0f) + (tempval & 0x0f) + (cpu.cpustatus & FLAG_CARRY);
 275  		if (temp > 9) temp += 6;
 276  		if (temp <= 0x0f)
 277  			temp = (temp & 0xf) + (cpu.a & 0xf0) + (tempval & 0xf0);
 278  		else
 279  		    temp = (temp & 0xf) + (cpu.a & 0xf0) + (tempval & 0xf0) + 0x10;
 280  		if (!((cpu.a + tempval + (cpu.cpustatus & FLAG_CARRY)) & 0xff))
 281  			setzero();
 282  		else
 283  			clearzero();
 284  		signcalc(temp);
 285  		if (((cpu.a ^ temp) & 0x80) && !((cpu.a ^ tempval) & 0x80))
 286  			setoverflow();
 287  		else
 288  			clearoverflow();
 289  		if ((temp & 0x1f0) > 0x90) temp += 0x60;
 290  		if ((temp & 0xff0) > 0xf0)
 291  			setcarry();
 292  		else
 293  			clearcarry();
 294  	} else {
 295          temp = tempval + cpu.a + (cpu.cpustatus & FLAG_CARRY);
 296          SETFLAGS(temp & 0xff);
 297          if (!((cpu.a ^ tempval) & 0x80) && ((cpu.a ^ temp) & 0x80))
 298              setoverflow();
 299          else
 300              clearoverflow();
 301          if (temp > 0xff)
 302              setcarry();
 303          else
 304              clearcarry();
 305      }
 306  	saveaccum(temp);
 307  }
 308  
 309  INLINEOP void _sbc(unsigned data) {
 310  	unsigned tempval = data;
 311  	unsigned temp;
 312  
 313  	temp = cpu.a - tempval - ((cpu.cpustatus & FLAG_CARRY) ^ FLAG_CARRY);
 314  
 315      if (cpu.cpustatus & FLAG_DECIMAL) {
 316  		unsigned tempval2;
 317  	  	tempval2 = (cpu.a & 0x0f) - (tempval & 0x0f) - ((cpu.cpustatus & FLAG_CARRY) ^ FLAG_CARRY);
 318  		if (tempval2 & 0x10)
 319  			tempval2 = ((tempval2 - 6) & 0xf) | ((cpu.a & 0xf0) - (tempval & 0xf0) - 0x10);
 320  		else
 321  			tempval2 = (tempval2 & 0xf) | ((cpu.a & 0xf0) - (tempval & 0xf0));
 322  		if (tempval2 & 0x100)
 323  			tempval2 -= 0x60;
 324  		if (temp < 0x100)
 325  			setcarry();
 326  		else
 327  			clearcarry();
 328  		SETFLAGS(temp & 0xff);
 329  		if (((cpu.a ^ temp) & 0x80) && ((cpu.a ^ tempval) & 0x80))
 330  			setoverflow();
 331  		else
 332  			clearoverflow();
 333  		saveaccum(tempval2);
 334  	} else {
 335  		SETFLAGS(temp & 0xff);
 336          if (temp < 0x100)
 337  			setcarry();
 338  		else
 339  			clearcarry();
 340  		if (((cpu.a ^ temp) & 0x80) && ((cpu.a ^ tempval) & 0x80))
 341  			 setoverflow();
 342  		else
 343  			clearoverflow();
 344  		saveaccum(temp);
 345      }
 346  
 347  }
 348  
 349  INLINEOP void adc() {
 350      unsigned data = getvalue();
 351  	_adc(data);
 352  }
 353  
 354  INLINEOP void adcZP() {
 355  	unsigned data = getvalueZP();
 356  	_adc(data);
 357  
 358  }
 359  
 360  INLINEOP void op_and() {
 361  	uint32_t result = cpu.a & getvalue();
 362  	zerocalc(result);
 363  	signcalc(result);
 364  	saveaccum(result);
 365  }
 366  
 367  INLINEOP void op_andZP() {
 368  	uint32_t result = cpu.a & getvalueZP();
 369  	zerocalc(result);
 370  	signcalc(result);
 371  	saveaccum(result);
 372  }
 373  
 374  INLINEOP void asl() {
 375  	uint32_t result = getvalue();
 376  	result <<=1;
 377  	carrycalc(result);
 378  	zerocalc(result);
 379  	signcalc(result);
 380  	putvalue(result);
 381  }
 382  
 383  INLINEOP void aslZP() {
 384  	uint32_t result = getvalueZP();
 385  	result <<=1;
 386  	carrycalc(result);
 387  	zerocalc(result);
 388  	signcalc(result);
 389  	putvalue(result);
 390  }
 391  
 392  INLINEOP void asla() {
 393  	uint32_t result = cpu.a << 1;
 394  	carrycalc(result);
 395  	zerocalc(result);
 396  	signcalc(result);
 397  	saveaccum(result);
 398  }
 399  
 400  INLINEOP void bcc() {
 401  	if ((cpu.cpustatus & FLAG_CARRY) == 0) {
 402  		uint32_t oldpc = cpu.pc;
 403  		cpu.pc += cpu.reladdr;
 404  		if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary
 405  		else cpu.ticks++;
 406  	}
 407  }
 408  
 409  INLINEOP void bcs() {
 410  	if ((cpu.cpustatus & FLAG_CARRY) == FLAG_CARRY) {
 411  		uint32_t oldpc = cpu.pc;
 412  		cpu.pc += cpu.reladdr;
 413  		if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary
 414  		else cpu.ticks++;
 415  	}
 416  }
 417  
 418  INLINEOP void beq() {
 419  	if ((cpu.cpustatus & FLAG_ZERO) == FLAG_ZERO) {
 420  		uint32_t oldpc = cpu.pc;
 421  		cpu.pc += cpu.reladdr;
 422  		if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary
 423  		else cpu.ticks++;
 424  	}
 425  }
 426  
 427  INLINEOP void op_bit() {
 428  	 unsigned value = getvalue();
 429  	 cpu.cpustatus = (cpu.cpustatus & ~(FLAG_SIGN|FLAG_OVERFLOW)) | (value & (FLAG_SIGN|FLAG_OVERFLOW));
 430  	 if (!(value & cpu.a))
 431  			setzero();
 432  		else
 433  			clearzero();
 434  /*
 435  	uint32_t value = getvalue();
 436  	uint32_t result = (uint16_t)cpu.a & value;
 437  
 438  	zerocalc(result);
 439  	cpu.cpustatus = (cpu.cpustatus & 0x3F) | (uint8_t)(value & 0xC0);
 440  */
 441  }
 442  
 443  INLINEOP void op_bitZP() {
 444  	unsigned value = getvalueZP();
 445  	cpu.cpustatus = (cpu.cpustatus & ~(FLAG_SIGN|FLAG_OVERFLOW)) | (value & (FLAG_SIGN|FLAG_OVERFLOW));
 446  	if (!(value & cpu.a))
 447  			setzero();
 448  		else
 449  			clearzero();
 450  }
 451  
 452  INLINEOP void bmi() {
 453  	if ((cpu.cpustatus & FLAG_SIGN) == FLAG_SIGN) {
 454  		uint32_t oldpc = cpu.pc;
 455  		cpu.pc += cpu.reladdr;
 456  		if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary
 457  		else cpu.ticks++;
 458  	}
 459  }
 460  
 461  INLINEOP void bne() {
 462  	if ((cpu.cpustatus & FLAG_ZERO) == 0) {
 463  		uint32_t oldpc = cpu.pc;
 464  		cpu.pc += cpu.reladdr;
 465  		if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary
 466  		else cpu.ticks++;
 467  	}
 468  }
 469  
 470  INLINEOP void bpl() {
 471  	if ((cpu.cpustatus & FLAG_SIGN) == 0) {
 472  		uint32_t oldpc = cpu.pc;
 473  		cpu.pc += cpu.reladdr;
 474  		if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary
 475  		else cpu.ticks++;
 476  	}
 477  }
 478  
 479  INLINEOP void brk() {
 480  	cpu.pc++;
 481  	push16(cpu.pc); //push next instruction address onto stack
 482  	push8(cpu.cpustatus | FLAG_BREAK); //push CPU cpustatus to stack
 483  	setinterrupt(); //set interrupt flag
 484  	cpu.pc = read6502(0xFFFE) | (read6502(0xFFFF) << 8);
 485  }
 486  
 487  INLINEOP void bvc() {
 488  	if ((cpu.cpustatus & FLAG_OVERFLOW) == 0) {
 489  		uint32_t oldpc = cpu.pc;
 490  		cpu.pc += cpu.reladdr;
 491  		if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary
 492  		else cpu.ticks++;
 493  	}
 494  }
 495  
 496  INLINEOP void bvs() {
 497  	if ((cpu.cpustatus & FLAG_OVERFLOW) == FLAG_OVERFLOW) {
 498  		uint32_t oldpc = cpu.pc;
 499  		cpu.pc += cpu.reladdr;
 500  		if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary
 501  		else cpu.ticks++;
 502  	}
 503  }
 504  
 505  INLINEOP void clc() {
 506  	clearcarry();
 507  }
 508  
 509  INLINEOP void cld() {
 510  	cleardecimal();
 511  }
 512  
 513  INLINEOP void cli_() {
 514  	clearinterrupt();
 515  }
 516  
 517  INLINEOP void clv() {
 518  	clearoverflow();
 519  }
 520  
 521  INLINEOP void cmp() {
 522  	uint16_t value = getvalue();
 523  	uint32_t result = (uint16_t)cpu.a - value;
 524  
 525  	if (cpu.a >= (uint8_t)(value & 0x00FF)) setcarry();
 526  	else clearcarry();
 527  	if (cpu.a == (uint8_t)(value & 0x00FF)) setzero();
 528  	else clearzero();
 529  	signcalc(result);
 530  }
 531  
 532  INLINEOP void cmpZP() {
 533  	uint16_t value = getvalueZP();
 534  	uint32_t result = (uint16_t)cpu.a - value;
 535  
 536  	if (cpu.a >= (uint8_t)(value & 0x00FF)) setcarry();
 537  	else clearcarry();
 538  	if (cpu.a == (uint8_t)(value & 0x00FF)) setzero();
 539  	else clearzero();
 540  	signcalc(result);
 541  }
 542  
 543  INLINEOP void cpx() {
 544  	uint16_t value = getvalue();
 545  	uint16_t result = (uint16_t)cpu.x - value;
 546  
 547  	if (cpu.x >= (uint8_t)(value & 0x00FF)) setcarry();
 548  	else clearcarry();
 549  	if (cpu.x == (uint8_t)(value & 0x00FF)) setzero();
 550  	else clearzero();
 551  	signcalc(result);
 552  }
 553  
 554  INLINEOP void cpxZP() {
 555  	uint16_t value = getvalueZP();
 556  	uint16_t result = (uint16_t)cpu.x - value;
 557  
 558  	if (cpu.x >= (uint8_t)(value & 0x00FF)) setcarry();
 559  	else clearcarry();
 560  	if (cpu.x == (uint8_t)(value & 0x00FF)) setzero();
 561  	else clearzero();
 562  	signcalc(result);
 563  }
 564  
 565  INLINEOP void cpy() {
 566  	uint16_t value = getvalue();
 567  	uint16_t result = (uint16_t)cpu.y - value;
 568  
 569  	if (cpu.y >= (uint8_t)(value & 0x00FF)) setcarry();
 570  	else clearcarry();
 571  	if (cpu.y == (uint8_t)(value & 0x00FF)) setzero();
 572  	else clearzero();
 573  	signcalc(result);
 574  }
 575  
 576  INLINEOP void cpyZP() {
 577  	uint16_t value = getvalueZP();
 578  	uint16_t result = (uint16_t)cpu.y - value;
 579  
 580  	if (cpu.y >= (uint8_t)(value & 0x00FF)) setcarry();
 581  	else clearcarry();
 582  	if (cpu.y == (uint8_t)(value & 0x00FF)) setzero();
 583  	else clearzero();
 584  	signcalc(result);
 585  }
 586  
 587  INLINEOP void dec() {
 588  	uint32_t result = getvalue() - 1;
 589  
 590  	zerocalc(result);
 591  	signcalc(result);
 592  
 593  	putvalue(result);
 594  }
 595  
 596  INLINEOP void decZP() {
 597  	uint32_t result = getvalueZP() - 1;
 598  
 599  	zerocalc(result);
 600  	signcalc(result);
 601  
 602  	putvalue(result);
 603  }
 604  
 605  INLINEOP void dex() {
 606  	cpu.x--;
 607  
 608  	zerocalc(cpu.x);
 609  	signcalc(cpu.x);
 610  }
 611  
 612  INLINEOP void dey() {
 613  	cpu.y--;
 614  
 615  	zerocalc(cpu.y);
 616  	signcalc(cpu.y);
 617  }
 618  
 619  INLINEOP void eor() {
 620  	uint32_t result = cpu.a ^ getvalue();
 621  
 622  	zerocalc(result);
 623  	signcalc(result);
 624  
 625  	saveaccum(result);
 626  }
 627  
 628  INLINEOP void eorZP() {
 629  	uint32_t result = cpu.a ^ getvalueZP();
 630  
 631  	zerocalc(result);
 632  	signcalc(result);
 633  
 634  	saveaccum(result);
 635  }
 636  
 637  INLINEOP void inc() {
 638  	uint32_t result = getvalue() + 1;
 639  
 640  	zerocalc(result);
 641  	signcalc(result);
 642  
 643  	putvalue(result);
 644  }
 645  
 646  INLINEOP void incZP() {
 647  	uint32_t result = getvalueZP() + 1;
 648  
 649  	zerocalc(result);
 650  	signcalc(result);
 651  
 652  	putvalue(result);
 653  }
 654  
 655  INLINEOP void inx() {
 656  	cpu.x++;
 657  
 658  	zerocalc(cpu.x);
 659  	signcalc(cpu.x);
 660  }
 661  
 662  INLINEOP void iny() {
 663  	cpu.y++;
 664  
 665  	zerocalc(cpu.y);
 666  	signcalc(cpu.y);
 667  }
 668  
 669  INLINEOP void jmp() {
 670  	cpu.pc = cpu.ea;
 671  }
 672  
 673  INLINEOP void jsr() {
 674  	push16(cpu.pc - 1);
 675  	cpu.pc = cpu.ea;
 676  }
 677  
 678  INLINEOP void lda() {
 679  	cpu.a = getvalue();
 680  
 681  	zerocalc(cpu.a);
 682  	signcalc(cpu.a);
 683  }
 684  
 685  INLINEOP void ldaZP() {
 686  	cpu.a = getvalueZP();
 687  
 688  	zerocalc(cpu.a);
 689  	signcalc(cpu.a);
 690  }
 691  
 692  INLINEOP void ldx() {
 693  	cpu.x = getvalue();
 694  
 695  	zerocalc(cpu.x);
 696  	signcalc(cpu.x);
 697  }
 698  
 699  INLINEOP void ldxZP() {
 700  	cpu.x = getvalue();
 701  
 702  	zerocalc(cpu.x);
 703  	signcalc(cpu.x);
 704  }
 705  
 706  INLINEOP void ldy() {
 707  	cpu.y = getvalue();
 708  
 709  	zerocalc(cpu.y);
 710  	signcalc(cpu.y);
 711  }
 712  
 713  INLINEOP void ldyZP() {
 714  	cpu.y = getvalueZP();
 715  
 716  	zerocalc(cpu.y);
 717  	signcalc(cpu.y);
 718  }
 719  
 720  INLINEOP void lsr() {
 721  	uint32_t value = getvalue();
 722  	uint32_t result = value >> 1;
 723  
 724  	if (value & 1) setcarry();
 725  	else clearcarry();
 726  	zerocalc(result);
 727  	//clearsign();
 728  	signcalc(result);
 729  
 730  	putvalue(result);
 731  }
 732  
 733  INLINEOP void lsrZP() {
 734  	uint32_t value = getvalue();
 735  	uint32_t result = value >> 1;
 736  
 737  	if (value & 1) setcarry();
 738  	else clearcarry();
 739  	zerocalc(result);
 740  	//clearsign();
 741  	signcalc(result);
 742  
 743  	putvalue(result);
 744  }
 745  
 746  INLINEOP void lsra() {
 747  	uint8_t value = cpu.a;
 748  	uint8_t result = value >> 1;
 749  
 750  	if (value & 1) setcarry();
 751  	else clearcarry();
 752  	zerocalc(result);
 753  	//clearsign();
 754  	signcalc(result);
 755  	saveaccum(result);
 756  }
 757  
 758  INLINEOP void ora() {
 759  
 760  	uint32_t result = cpu.a | getvalue();
 761  
 762  	zerocalc(result);
 763  	signcalc(result);
 764  
 765  	saveaccum(result);
 766  }
 767  
 768  INLINEOP void oraZP() {
 769  
 770  	uint32_t result = cpu.a | getvalueZP();
 771  
 772  	zerocalc(result);
 773  	signcalc(result);
 774  
 775  	saveaccum(result);
 776  }
 777  
 778  INLINEOP void pha() {
 779  	push8(cpu.a);
 780  }
 781  
 782  INLINEOP void php() {
 783  	push8(cpu.cpustatus | FLAG_BREAK);
 784  }
 785  
 786  INLINEOP void pla() {
 787  	cpu.a = pull8();
 788  
 789  	zerocalc(cpu.a);
 790  	signcalc(cpu.a);
 791  }
 792  
 793  INLINEOP void plp() {
 794  	cpu.cpustatus = (pull8() & 0xef) | FLAG_CONSTANT;
 795  }
 796  
 797  INLINEOP void rol() {
 798  	uint16_t value = getvalue();
 799  	uint16_t result = (value << 1) | (cpu.cpustatus & FLAG_CARRY);
 800  
 801  	carrycalc(result);
 802  	zerocalc(result);
 803  	signcalc(result);
 804  
 805  	putvalue(result);
 806  }
 807  
 808  INLINEOP void rolZP() {
 809  	uint16_t value = getvalueZP();
 810  	uint16_t result = (value << 1) | (cpu.cpustatus & FLAG_CARRY);
 811  
 812  	carrycalc(result);
 813  	zerocalc(result);
 814  	signcalc(result);
 815  
 816  	putvalue(result);
 817  }
 818  
 819  INLINEOP void rola() {
 820  	uint16_t value = cpu.a;
 821  	uint16_t result = (value << 1) | (cpu.cpustatus & FLAG_CARRY);
 822  
 823  	carrycalc(result);
 824  	zerocalc(result);
 825  	signcalc(result);
 826  	saveaccum(result);
 827  }
 828  
 829  INLINEOP void ror() {
 830  	uint32_t value = getvalue();
 831  	uint16_t result = (value >> 1) | ((cpu.cpustatus & FLAG_CARRY) << 7);
 832  
 833  	if (value & 1) setcarry();
 834  	else clearcarry();
 835  	zerocalc(result);
 836  	signcalc(result);
 837  
 838  	putvalue(result);
 839  }
 840  
 841  INLINEOP void rorZP() {
 842  	uint32_t value = getvalueZP();
 843  	uint16_t result = (value >> 1) | ((cpu.cpustatus & FLAG_CARRY) << 7);
 844  
 845  	if (value & 1) setcarry();
 846  	else clearcarry();
 847  	zerocalc(result);
 848  	signcalc(result);
 849  
 850  	putvalue(result);
 851  }
 852  
 853  INLINEOP void rora() {
 854  	uint32_t value = cpu.a;
 855  	uint16_t result = (value >> 1) | ((cpu.cpustatus & FLAG_CARRY) << 7);
 856  
 857  	if (value & 1) setcarry();
 858  	else clearcarry();
 859  	zerocalc(result);
 860  	signcalc(result);
 861  	saveaccum(result);
 862  }
 863  
 864  
 865  INLINEOP void rti() {
 866  	cpu.cpustatus = pull8();
 867  	cpu.pc = pull16();
 868  }
 869  
 870  INLINEOP void rts() {
 871  	cpu.pc = pull16() + 1;
 872  }
 873  
 874  INLINEOP void sbc() {
 875      unsigned data = getvalue();
 876  	_sbc(data);
 877  }
 878  
 879  INLINEOP void sbcZP() {
 880  	 unsigned data = getvalueZP();
 881  	_sbc(data);
 882  }
 883  
 884  
 885  INLINEOP void sec() {
 886  	setcarry();
 887  }
 888  
 889  INLINEOP void sed() {
 890  	setdecimal();
 891  }
 892  
 893  INLINEOP void sei_() {
 894  	setinterrupt();
 895  }
 896  
 897  INLINEOP void sta() {
 898  	putvalue(cpu.a);
 899  }
 900  
 901  INLINEOP void stx() {
 902  	putvalue(cpu.x);
 903  }
 904  
 905  INLINEOP void sty() {
 906  	putvalue(cpu.y);
 907  }
 908  
 909  INLINEOP void tax() {
 910  	cpu.x = cpu.a;
 911  
 912  	zerocalc(cpu.x);
 913  	signcalc(cpu.x);
 914  }
 915  
 916  INLINEOP void tay() {
 917  	cpu.y = cpu.a;
 918  
 919  	zerocalc(cpu.y);
 920  	signcalc(cpu.y);
 921  }
 922  
 923  INLINEOP void tsx() {
 924  
 925  	cpu.x = cpu.sp;
 926  
 927  	zerocalc(cpu.x);
 928  	signcalc(cpu.x);
 929  
 930  }
 931  
 932  INLINEOP void txa() {
 933  	cpu.a = cpu.x;
 934  
 935  	zerocalc(cpu.a);
 936  	signcalc(cpu.a);
 937  }
 938  
 939  INLINEOP void txs() {
 940  	cpu.sp = cpu.x;
 941  }
 942  
 943  INLINEOP void tya() {
 944  	cpu.a = cpu.y;
 945  
 946  	zerocalc(cpu.a);
 947  	signcalc(cpu.a);
 948  }
 949  
 950  
 951  //undocumented instructions
 952  INLINEOP void lax() {
 953  	lda();
 954  	ldx();
 955  }
 956  
 957  INLINEOP void sax() {
 958  	sta();
 959  	stx();
 960  	putvalue(cpu.a & cpu.x);
 961  }
 962  
 963  INLINEOP void dcp() {
 964  	dec();
 965  	cmp();
 966  }
 967  
 968  INLINEOP void isb() {
 969  	inc();
 970  	sbc();
 971  }
 972  
 973  INLINEOP void slo() {
 974  	asl();
 975  	ora();
 976  }
 977  
 978  INLINEOP void rla() {
 979  	rol();
 980  	op_and();
 981  }
 982  
 983  INLINEOP void sre() {
 984  	lsr();
 985  	eor();
 986  }
 987  
 988  INLINEOP void rra() {
 989  	ror();
 990  	adc();
 991  }
 992  
 993  INLINEOP void alr() { // (FB)
 994  
 995  	uint32_t result = cpu.a & getvalue() ;
 996  
 997  	if (result & 1) setcarry();
 998  	else clearcarry();
 999  
1000  	result = result / 2;
1001  
1002  	clearsign();
1003  	zerocalc(result);
1004  	saveaccum(result);
1005  }
1006  
1007  INLINEOP void arr() { //This one took me hours.. finally taken from VICE (FB)
1008     uint32_t result;
1009     result = cpu.a & getvalue();
1010     if (!(cpu.cpustatus & FLAG_DECIMAL)) {
1011  		result >>= 1;
1012  		result |= ((cpu.cpustatus & FLAG_CARRY) << 7);
1013  		signcalc(result);
1014  		zerocalc(result);
1015  		if (result & 0x40) setcarry(); else clearcarry();
1016  		if ((result & 0x40) ^ ((result & 0x20)<<1)) setoverflow(); else clearoverflow();
1017  		saveaccum(result);
1018     } else {
1019  		uint32_t t2 = result;
1020  		t2 >>= 1;
1021  		t2 |= ((cpu.cpustatus & FLAG_CARRY) << 7);
1022  		if (cpu.cpustatus & FLAG_CARRY) setsign(); else clearsign();
1023  		zerocalc(t2);
1024  		if ((t2 ^ result) & 0x40) setoverflow(); else clearoverflow();
1025  	    if (((result & 0xf) + (result & 0x1)) > 0x5) {
1026                  t2 = (t2 & 0xf0) | ((t2 + 0x6) & 0xf);
1027          }
1028          if (((result & 0xf0) + (result & 0x10)) > 0x50) {
1029                  t2 = (t2 & 0x0f) | ((t2 + 0x60) & 0xf0);
1030                  setcarry();
1031          } else {
1032                  clearcarry();
1033          }
1034  	   saveaccum(t2);
1035     }
1036  
1037  }
1038  
1039  INLINEOP void xaa() { // AKA ANE
1040  	const uint32_t val = 0xee; // VICE uses 0xff - but this results in an error in the testsuite (FB)
1041  	uint32_t result = (cpu.a | val) & cpu.x & getvalue();
1042  	signcalc(result);
1043  	zerocalc(result);
1044  	saveaccum(result);
1045  }
1046  
1047  INLINEOP void lxa() {
1048  	const uint32_t val = 0xee;
1049  	uint32_t result = (cpu.a | val) & getvalue();
1050  	signcalc(result);
1051  	zerocalc(result);
1052  	cpu.x = result;
1053  	saveaccum(result);
1054  }
1055  
1056  INLINEOP void axs() { //aka SBX
1057      uint32_t result = getvalue();
1058      result = (cpu.a & cpu.x) - result;
1059  	cpu.x = result;
1060  	if (result < 0x100) setcarry(); else clearcarry();
1061  	zerocalc(cpu.x);
1062  	signcalc(cpu.x);
1063  }
1064  
1065  INLINEOP void ahx() { //todo (is unstable)
1066  	UNSUPPORTED
1067  }
1068  
1069  INLINEOP void anc() {
1070  	uint32_t result = cpu.a & getvalue();
1071  	signcalc(result)
1072      zerocalc(result);
1073  	if (cpu.cpustatus & FLAG_SIGN) setcarry(); else clearcarry();
1074      saveaccum(result);
1075  }
1076  
1077  INLINEOP void las() {
1078  	uint32_t result = cpu.sp & getvalue();
1079  	signcalc(result);
1080  	zerocalc(result);
1081  	cpu.sp = result;
1082  	cpu.x = result;
1083  	saveaccum(result);
1084  }
1085  
1086  /********************************************************************************************************************/
1087  /* OPCODES																																																					*/
1088  /********************************************************************************************************************/
1089  
1090  OPCODE void opKIL(void) {
1091  	printf("CPU JAM @ $%d\n",cpu.pc);
1092  	cpu_reset();
1093  }
1094  
1095  OPCODE void op0x0(void) {
1096  	cpu.ticks = 7;
1097  	imp();
1098  	brk();
1099  }
1100  
1101  OPCODE void op0x1(void) {
1102  	cpu.ticks = 6;
1103  	indx();
1104  	ora();
1105  }
1106  
1107  OPCODE void op0x3(void) { //undocumented
1108  	cpu.ticks = 8;
1109  	indx();
1110  	slo();
1111  }
1112  
1113  OPCODE void op0x4(void) { //nop read zeropage
1114  	cpu.ticks = 3;
1115  	zp();
1116  }
1117  
1118  OPCODE void op0x5(void) {
1119  	cpu.ticks = 3;
1120  	zp();
1121  	oraZP();
1122  }
1123  
1124  OPCODE void op0x6(void) {
1125  	cpu.ticks = 5;
1126  	zp();
1127  	aslZP();
1128  }
1129  
1130  OPCODE void op0x7(void) { //undocumented SLO
1131  	cpu.ticks = 5;
1132  	zp();
1133  	slo();
1134  }
1135  
1136  OPCODE void op0x8(void) {
1137  	cpu.ticks = 3;
1138  	imp();
1139  	php();
1140  }
1141  
1142  OPCODE void op0x9(void) {
1143  	cpu.ticks = 2;
1144  	imm();
1145  	ora();
1146  }
1147  
1148  OPCODE void op0xA(void) {
1149  	cpu.ticks = 2;
1150  	//acc();
1151  	asla();
1152  }
1153  
1154  OPCODE void op0xB(void) { //undocumented
1155  	cpu.ticks = 2;
1156  	imm();
1157  	anc();
1158  }
1159  
1160  OPCODE void op0xC(void) { //nop
1161  	cpu.ticks = 4;
1162  	abso();
1163  }
1164  
1165  OPCODE void op0xD(void) {
1166  	cpu.ticks = 4;
1167  	abso();
1168  	ora();
1169  }
1170  
1171  OPCODE void op0xE(void) {
1172  	cpu.ticks = 6;
1173  	abso();
1174  	asl();
1175  }
1176  
1177  OPCODE void op0xF(void) { //undocumented
1178  	cpu.ticks = 6;
1179  	abso();
1180  	slo();
1181  }
1182  
1183  OPCODE void op0x10(void) {
1184  	cpu.ticks = 2;
1185  	rel();
1186  	bpl();
1187  }
1188  
1189  OPCODE void op0x11(void) {
1190  	cpu.ticks = 5;
1191  	indy_t();
1192  	ora();
1193  }
1194  
1195  OPCODE void op0x13(void) { //undocumented
1196  	cpu.ticks = 8;
1197  	indy();
1198  	slo();
1199  }
1200  
1201  OPCODE void op0x14(void) { //nop
1202  	cpu.ticks = 4;
1203  	zpx();
1204  }
1205  
1206  OPCODE void op0x15(void) {
1207  	cpu.ticks = 4;
1208  	zpx();
1209  	ora();
1210  }
1211  
1212  OPCODE void op0x16(void) {
1213  	cpu.ticks = 6;
1214  	zpx();
1215  	asl();
1216  }
1217  
1218  OPCODE void op0x17(void) { //undocumented
1219  	cpu.ticks = 6;
1220  	//zpy(); bug
1221  	zpx();
1222  	slo();
1223  }
1224  
1225  OPCODE void op0x18(void) {
1226  	cpu.ticks = 2;
1227  	imp();
1228  	clc();
1229  }
1230  
1231  OPCODE void op0x19(void) {
1232  	cpu.ticks = 4;
1233  	absy_t();
1234  	ora();
1235  }
1236  
1237  OPCODE void op0x1A(void) { //nop
1238  	cpu.ticks = 2;
1239  }
1240  
1241  OPCODE void op0x1B(void) { //undocumented
1242  	cpu.ticks = 7;
1243  	absy();
1244  	slo();
1245  }
1246  
1247  OPCODE void op0x1C(void) { //nop
1248  	cpu.ticks = 4;
1249  	 //();
1250  }
1251  
1252  OPCODE void op0x1D(void) {
1253  	cpu.ticks = 4;
1254  	absx_t();
1255  	ora();
1256  }
1257  
1258  OPCODE void op0x1E(void) {
1259  	cpu.ticks = 7;
1260  	absx();
1261  	asl();
1262  }
1263  
1264  
1265  OPCODE void op0x1F(void) { //undocumented
1266  	cpu.ticks = 7;
1267  	absx();
1268  	slo();
1269  }
1270  
1271  OPCODE void op0x20(void) {
1272  	cpu.ticks = 6;
1273  	abso();
1274  	jsr();
1275  }
1276  
1277  OPCODE void op0x21(void) {
1278  	cpu.ticks = 6;
1279  	indx();
1280  	op_and();
1281  }
1282  
1283  OPCODE void op0x23(void) { //undocumented
1284  	cpu.ticks = 8;
1285  	indx();
1286  	rla();
1287  }
1288  
1289  OPCODE void op0x24(void) {
1290  	cpu.ticks = 3;
1291  	zp();
1292  	op_bitZP();
1293  }
1294  
1295  OPCODE void op0x25(void) {
1296  	cpu.ticks = 3;
1297  	zp();
1298  	op_and();
1299  }
1300  
1301  OPCODE void op0x26(void) {
1302  	cpu.ticks = 5;
1303  	zp();
1304  	rolZP();
1305  }
1306  
1307  OPCODE void op0x27(void) { //undocumented
1308  	cpu.ticks = 5;
1309  	zp();
1310  	rla();
1311  }
1312  
1313  OPCODE void op0x28(void) {
1314  	cpu.ticks = 4;
1315  	imp();
1316  	plp();
1317  }
1318  
1319  OPCODE void op0x29(void) {
1320  	cpu.ticks = 2;
1321  	imm();
1322  	op_and();
1323  }
1324  
1325  OPCODE void op0x2A(void) {
1326  	cpu.ticks = 2;
1327  	//acc();
1328  	rola();
1329  }
1330  
1331  OPCODE void op0x2B(void) { //undocumented
1332  	cpu.ticks = 2;
1333  	imm();
1334  	anc();
1335  }
1336  
1337  OPCODE void op0x2C(void) {
1338  	cpu.ticks = 4;
1339  	abso();
1340  	op_bit();
1341  }
1342  
1343  OPCODE void op0x2D(void) {
1344  	cpu.ticks = 4;
1345  	abso();
1346  	op_and();
1347  }
1348  
1349  OPCODE void op0x2E(void) {
1350  	cpu.ticks = 6;
1351  	abso();
1352  	rol();
1353  }
1354  
1355  OPCODE void op0x2F(void) { //undocumented
1356  	cpu.ticks = 6;
1357  	abso();
1358  	rla();
1359  }
1360  
1361  OPCODE void op0x30(void) {
1362  	cpu.ticks = 2;
1363  	rel();
1364  	bmi();
1365  }
1366  
1367  OPCODE void op0x31(void) {
1368  	cpu.ticks = 5;
1369  	indy_t();
1370  	op_and();
1371  }
1372  
1373  OPCODE void op0x33(void) { //undocumented
1374  	cpu.ticks = 8;
1375  	indy();
1376  	rla();
1377  }
1378  
1379  OPCODE void op0x34(void) { //nop
1380  	cpu.ticks = 4;
1381  	zpx();
1382  }
1383  
1384  OPCODE void op0x35(void) {
1385  	cpu.ticks = 4;
1386  	zpx();
1387  	op_and();
1388  }
1389  
1390  OPCODE void op0x36(void) {
1391  	cpu.ticks = 6;
1392  	zpx();
1393  	rol();
1394  }
1395  
1396  OPCODE void op0x37(void) { //undocumented
1397  	cpu.ticks = 6;
1398  	zpx();
1399  	rla();
1400  }
1401  
1402  OPCODE void op0x38(void) {
1403  	cpu.ticks = 2;
1404  	imp();
1405  	sec();
1406  }
1407  
1408  OPCODE void op0x39(void) {
1409  	cpu.ticks = 4;
1410  	absy_t();
1411  	op_and();
1412  }
1413  
1414  OPCODE void op0x3A(void) { //nop
1415  	cpu.ticks = 2;
1416  }
1417  
1418  OPCODE void op0x3B(void) { //undocumented
1419  	cpu.ticks = 7;
1420  	absy();
1421  	rla();
1422  }
1423  
1424  OPCODE void op0x3C(void) { //nop
1425  	cpu.ticks = 4;
1426  	absx_t();
1427  }
1428  
1429  OPCODE void op0x3D(void) {
1430  	cpu.ticks = 4;
1431  	absx_t();
1432  	op_and();
1433  }
1434  
1435  OPCODE void op0x3E(void) {
1436  	cpu.ticks = 7;
1437  	absx();
1438  	rol();
1439  }
1440  
1441  OPCODE void op0x3F(void) { //undocumented
1442  	cpu.ticks = 7;
1443  	absx();
1444  	rla();
1445  }
1446  
1447  OPCODE void op0x40(void) {
1448  	cpu.ticks = 6;
1449  	imp();
1450  	rti();
1451  }
1452  
1453  OPCODE void op0x41(void) {
1454  	cpu.ticks = 6;
1455  	indx();
1456  	eor();
1457  }
1458  
1459  OPCODE void op0x43(void) { //undocumented
1460  	cpu.ticks = 8;
1461  	indx();
1462  	sre();
1463  }
1464  
1465  OPCODE void op0x44(void) { //nop
1466  	cpu.ticks = 3;
1467  	zp();
1468  }
1469  
1470  OPCODE void op0x45(void) {
1471  	cpu.ticks = 3;
1472  	zp();
1473  	eorZP();
1474  }
1475  
1476  OPCODE void op0x46(void) {
1477  	cpu.ticks = 5;
1478  	zp();
1479  	lsrZP();
1480  }
1481  
1482  OPCODE void op0x47(void) { //undocumented
1483  	cpu.ticks = 5;
1484  	zp();
1485  	sre();
1486  }
1487  
1488  OPCODE void op0x48(void) {
1489  	cpu.ticks = 3;
1490  	imp();
1491  	pha();
1492  }
1493  
1494  OPCODE void op0x49(void) {
1495  	cpu.ticks = 2;
1496  	imm();
1497  	eor();
1498  }
1499  
1500  OPCODE void op0x4A(void) {
1501  	cpu.ticks = 2;
1502  //	acc();
1503  	lsra();
1504  }
1505  
1506  OPCODE void op0x4B(void) { //undocumented
1507  	cpu.ticks = 2;
1508  	imm();
1509  	alr();
1510  }
1511  
1512  OPCODE void op0x4C(void) {
1513  	cpu.ticks = 3;
1514  	abso();
1515  	jmp();
1516  }
1517  
1518  OPCODE void op0x4D(void) {
1519  	cpu.ticks = 4;
1520  	abso();
1521  	eor();
1522  }
1523  
1524  OPCODE void op0x4E(void) {
1525  	cpu.ticks = 6;
1526  	abso();
1527  	lsr();
1528  }
1529  
1530  OPCODE void op0x4F(void) { //undocumented
1531  	cpu.ticks = 6;
1532  	abso();
1533  	sre();
1534  }
1535  
1536  OPCODE void op0x50(void) {
1537  	cpu.ticks = 2;
1538  	rel();
1539  	bvc();
1540  }
1541  
1542  OPCODE void op0x51(void) {
1543  	cpu.ticks = 5;
1544  	indy_t();
1545  	eor();
1546  }
1547  
1548  OPCODE void op0x53(void) { //undocumented
1549  	cpu.ticks = 8;
1550  	//zp(); BUG
1551  	indy();
1552  	sre();
1553  }
1554  
1555  OPCODE void op0x54(void) { //nop
1556  	cpu.ticks = 4;
1557  	zpx();
1558  }
1559  
1560  OPCODE void op0x55(void) {
1561  	cpu.ticks = 4;
1562  	zpx();
1563  	eor();
1564  }
1565  
1566  OPCODE void op0x56(void) {
1567  	cpu.ticks = 6;
1568  	zpx();
1569  	lsr();
1570  }
1571  
1572  OPCODE void op0x57(void) { //undocumented
1573  	cpu.ticks = 6;
1574  	zpx();
1575  	sre();
1576  }
1577  
1578  OPCODE void op0x58(void) {
1579  	cpu.ticks = 2;
1580  	imp();
1581  	cli_();
1582  }
1583  
1584  OPCODE void op0x59(void) {
1585  	cpu.ticks = 4;
1586  	absy_t();
1587  	eor();
1588  }
1589  
1590  OPCODE void op0x5A(void) { //nop
1591  	cpu.ticks = 2;
1592  }
1593  
1594  OPCODE void op0x5B(void) { //undocumented
1595  	cpu.ticks = 7;
1596  	absy();
1597  	sre();
1598  }
1599  
1600  OPCODE void op0x5C(void) { //nop
1601  	cpu.ticks = 4;
1602  	absx_t();
1603  }
1604  
1605  OPCODE void op0x5D(void) {
1606  	cpu.ticks = 4;
1607  	absx_t();
1608  	eor();
1609  }
1610  
1611  OPCODE void op0x5E(void) {
1612  	cpu.ticks = 7;
1613  	absx();
1614  	lsr();
1615  }
1616  
1617  OPCODE void op0x5F(void) { //undocumented
1618  	cpu.ticks = 7;
1619  	absx();
1620  	sre();
1621  }
1622  
1623  OPCODE void op0x60(void) {
1624  	cpu.ticks = 6;
1625  	imp();
1626  	rts();
1627  }
1628  
1629  OPCODE void op0x61(void) {
1630  	cpu.ticks = 6;
1631  	indx();
1632  	adc();
1633  }
1634  
1635  OPCODE void op0x63(void) { //undocumented
1636  	cpu.ticks = 8;
1637  	indx();
1638  	rra();
1639  }
1640  
1641  OPCODE void op0x64(void) {
1642  	cpu.ticks = 3;
1643  	zp();
1644  }
1645  
1646  OPCODE void op0x65(void) {
1647  	cpu.ticks = 3;
1648  	zp();
1649  	adcZP();
1650  }
1651  
1652  OPCODE void op0x66(void) {
1653  	cpu.ticks = 5;
1654  	zp();
1655  	rorZP();
1656  }
1657  
1658  OPCODE void op0x67(void) { //undocumented
1659  	cpu.ticks = 5;
1660  	zp();
1661  	rra();
1662  }
1663  
1664  OPCODE void op0x68(void) {
1665  	cpu.ticks = 4;
1666  	imp();
1667  	pla();
1668  }
1669  
1670  OPCODE void op0x69(void) {
1671  	cpu.ticks = 2;
1672  	imm();
1673  	adc();
1674  }
1675  
1676  OPCODE void op0x6A(void) {
1677  	cpu.ticks = 2;
1678  //	acc();
1679  	rora();
1680  }
1681  
1682  OPCODE void op0x6B(void) { //undocumented
1683  	cpu.ticks = 2;
1684  	imm();
1685  	arr();
1686  }
1687  
1688  OPCODE void op0x6C(void) {
1689  	cpu.ticks = 5;
1690  	ind();
1691  	jmp();
1692  }
1693  
1694  OPCODE void op0x6D(void) {
1695  	cpu.ticks = 4;
1696  	abso();
1697  	adc();
1698  }
1699  
1700  OPCODE void op0x6E(void) {
1701  	cpu.ticks = 6;
1702  	abso();
1703  	ror();
1704  }
1705  
1706  OPCODE void op0x6F(void) { //undocumented
1707  	cpu.ticks = 6;
1708  	abso();
1709  	rra();
1710  }
1711  
1712  OPCODE void op0x70(void) {
1713  	cpu.ticks = 2;
1714  	rel();
1715  	bvs();
1716  }
1717  
1718  OPCODE void op0x71(void) {
1719  	cpu.ticks = 5;
1720  	indy_t();
1721  	adc();
1722  }
1723  
1724  OPCODE void op0x73(void) { //undocumented
1725  	cpu.ticks = 8;
1726  	indy();
1727  	rra();
1728  }
1729  
1730  OPCODE void op0x74(void) { //nop
1731  	cpu.ticks = 4;
1732  	zpx();
1733  }
1734  
1735  OPCODE void op0x75(void) {
1736  	cpu.ticks = 4;
1737  	zpx();
1738  	adc();
1739  }
1740  
1741  OPCODE void op0x76(void) {
1742  	cpu.ticks = 6;
1743  	zpx();
1744  	ror();
1745  }
1746  
1747  OPCODE void op0x77(void) { //undocumented
1748  	cpu.ticks = 6;
1749  	zpx();
1750  	rra();
1751  }
1752  
1753  OPCODE void op0x78(void) {
1754  	cpu.ticks = 2;
1755  	imp();
1756  	sei_();
1757  }
1758  
1759  OPCODE void op0x79(void) {
1760  	cpu.ticks = 4;
1761  	absy_t();
1762  	adc();
1763  }
1764  
1765  OPCODE void op0x7A(void) { //nop
1766  	cpu.ticks = 2;
1767  }
1768  
1769  OPCODE void op0x7B(void) { //undocumented
1770  	cpu.ticks = 7;
1771  	absy();
1772  	rra();
1773  }
1774  
1775  OPCODE void op0x7C(void) { //nop
1776  	cpu.ticks = 4;
1777  	absx_t();
1778  }
1779  
1780  OPCODE void op0x7D(void) {
1781  	cpu.ticks = 4;
1782  	absx_t();
1783  	adc();
1784  }
1785  
1786  OPCODE void op0x7E(void) {
1787  	cpu.ticks = 7;
1788  	absx();
1789  	ror();
1790  }
1791  
1792  OPCODE void op0x7F(void) { //undocumented
1793  	cpu.ticks = 7;
1794  	absx();
1795  	rra();
1796  }
1797  
1798  OPCODE void op0x80(void) { //nop
1799  	cpu.ticks = 2;
1800  	imm();
1801  }
1802  
1803  OPCODE void op0x81(void) {
1804  	cpu.ticks = 6;
1805  	indx();
1806  	sta();
1807  }
1808  
1809  OPCODE void op0x82(void) { //nop
1810  	cpu.ticks = 2;
1811  	imm();
1812  }
1813  
1814  OPCODE void op0x83(void) { //undocumented
1815  	cpu.ticks = 6;
1816  	indx();
1817  	sax();
1818  }
1819  
1820  OPCODE void op0x84(void) {
1821  	cpu.ticks = 3;
1822  	zp();
1823  	sty();
1824  }
1825  
1826  OPCODE void op0x85(void) {
1827  	cpu.ticks = 3;
1828  	zp();
1829  	sta();
1830  }
1831  
1832  OPCODE void op0x86(void) {
1833  	cpu.ticks = 3;
1834  	zp();
1835  	stx();
1836  }
1837  
1838  OPCODE void op0x87(void) { //undocumented
1839  	cpu.ticks = 3;
1840  	zp();
1841  	sax();
1842  }
1843  
1844  OPCODE void op0x88(void) {
1845  	cpu.ticks = 2;
1846  	imp();
1847  	dey();
1848  }
1849  
1850  OPCODE void op0x89(void) { //nop
1851  	cpu.ticks = 2;
1852  	imm();
1853  }
1854  
1855  OPCODE void op0x8A(void) {
1856  	cpu.ticks = 2;
1857  	imp();
1858  	txa();
1859  }
1860  
1861  OPCODE void op0x8B(void) { //undocumented
1862  	cpu.ticks = 2;
1863  	imm();
1864  	xaa();
1865  }
1866  
1867  OPCODE void op0x8C(void) {
1868  	cpu.ticks = 4;
1869  	abso();
1870  	sty();
1871  }
1872  
1873  OPCODE void op0x8D(void) {
1874  	cpu.ticks = 4;
1875  	abso();
1876  	sta();
1877  }
1878  
1879  OPCODE void op0x8E(void) {
1880  	cpu.ticks = 4;
1881  	abso();
1882  	stx();
1883  }
1884  
1885  OPCODE void op0x8F(void) { //undocumented
1886  	cpu.ticks = 4;
1887  	abso();
1888  	sax();
1889  }
1890  
1891  OPCODE void op0x90(void) {
1892  	cpu.ticks = 2;
1893  	rel();
1894  	bcc();
1895  }
1896  
1897  OPCODE void op0x91(void) {
1898  	cpu.ticks = 6;
1899  	indy();
1900  	sta();
1901  }
1902  
1903  OPCODE void op0x93(void) { //undocumented
1904  	cpu.ticks = 6;
1905  	indy();
1906  	ahx();
1907  }
1908  
1909  OPCODE void op0x94(void) {
1910  	cpu.ticks = 4;
1911  	zpx();
1912  	sty();
1913  }
1914  
1915  OPCODE void op0x95(void) {
1916  	cpu.ticks = 4;
1917  	zpx();
1918  	sta();
1919  }
1920  
1921  OPCODE void op0x96(void) {
1922  	cpu.ticks = 4;
1923  	zpy();
1924  	stx();
1925  }
1926  
1927  OPCODE void op0x97(void) { //undocumented
1928  	cpu.ticks = 4;
1929  	zpy();
1930  	sax();
1931  }
1932  
1933  OPCODE void op0x98(void) {
1934  	cpu.ticks = 2;
1935  	imp();
1936  	tya();
1937  }
1938  
1939  OPCODE void op0x99(void) {
1940  	cpu.ticks = 5;
1941  	absy();
1942  	sta();
1943  }
1944  
1945  OPCODE void op0x9A(void) {
1946  	cpu.ticks = 2;
1947  	imp();
1948  	txs();
1949  }
1950  
1951  OPCODE void op0x9B(void) { //undocumented
1952  	cpu.ticks = 5;
1953  	absy();
1954  	//tas();
1955  	UNSUPPORTED;
1956  }
1957  
1958  OPCODE void op0x9C(void) { //undocumented
1959  	cpu.ticks = 5;
1960  	absy();
1961  	//shy();
1962  	UNSUPPORTED;
1963  }
1964  
1965  OPCODE void op0x9D(void) {
1966  	cpu.ticks = 5;
1967  	absx();
1968  	sta();
1969  }
1970  
1971  OPCODE void op0x9E(void) { //undocumented
1972  	cpu.ticks = 5;
1973  	absx();
1974  	//shx();
1975  }
1976  
1977  OPCODE void op0x9F(void) { //undocumented
1978  	cpu.ticks = 5;
1979  	absx();
1980  	ahx();
1981  }
1982  
1983  OPCODE void op0xA0(void) {
1984  	cpu.ticks = 2;
1985  	imm();
1986  	ldy();
1987  }
1988  
1989  OPCODE void op0xA1(void) {
1990  	cpu.ticks = 6;
1991  	indx();
1992  	lda();
1993  }
1994  
1995  OPCODE void op0xA2(void) {
1996  	cpu.ticks = 2;
1997  	imm();
1998  	ldx();
1999  }
2000  
2001  OPCODE void op0xA3(void) { //undocumented
2002  	cpu.ticks = 6;
2003  	indx();
2004  	lax();
2005  }
2006  
2007  OPCODE void op0xA4(void) {
2008  	cpu.ticks = 3;
2009  	zp();
2010  	ldyZP();
2011  }
2012  
2013  OPCODE void op0xA5(void) {
2014  	cpu.ticks = 3;
2015  	zp();
2016  	ldaZP();
2017  }
2018  
2019  OPCODE void op0xA6(void) {
2020  	cpu.ticks = 3;
2021  	zp();
2022  	ldxZP();
2023  }
2024  
2025  OPCODE void op0xA7(void) { //undocumented
2026  	cpu.ticks = 3;
2027  	zp();
2028  	lax();
2029  }
2030  
2031  OPCODE void op0xA8(void) {
2032  	cpu.ticks = 2;
2033  	imp();
2034  	tay();
2035  }
2036  
2037  OPCODE void op0xA9(void) {
2038  	cpu.ticks = 2;
2039  	imm();
2040  	lda();
2041  }
2042  
2043  OPCODE void op0xAA(void) {
2044  	cpu.ticks = 2;
2045  	imp();
2046  	tax();
2047  }
2048  
2049  OPCODE void op0xAB(void) { //undocumented
2050  	cpu.ticks = 2;
2051  	imm();
2052  	lxa();
2053  }
2054  
2055  OPCODE void op0xAC(void) {
2056  	cpu.ticks = 4;
2057  	abso();
2058  	ldy();
2059  }
2060  
2061  OPCODE void op0xAD(void) {
2062  	cpu.ticks = 4;
2063  	abso();
2064  	lda();
2065  }
2066  
2067  OPCODE void op0xAE(void) {
2068  	cpu.ticks = 4;
2069  	abso();
2070  	ldx();
2071  }
2072  
2073  OPCODE void op0xAF(void) { //undocumented
2074  	cpu.ticks = 4;
2075  	abso();
2076  	lax();
2077  }
2078  
2079  OPCODE void op0xB0(void) {
2080  	cpu.ticks = 2;
2081  	rel();
2082  	bcs();
2083  }
2084  
2085  OPCODE void op0xB1(void) {
2086  	cpu.ticks = 5;
2087  	indy_t();
2088  	lda();
2089  }
2090  
2091  OPCODE void op0xB3(void) { //undocumented
2092  	cpu.ticks = 5;
2093  	indy_t();
2094  	lax();
2095  }
2096  
2097  OPCODE void op0xB4(void) {
2098  	cpu.ticks = 4;
2099  	zpx();
2100  	ldy();
2101  }
2102  
2103  OPCODE void op0xB5(void) {
2104  	cpu.ticks = 4;
2105  	zpx();
2106  	lda();
2107  }
2108  
2109  OPCODE void op0xB6(void) {
2110  	cpu.ticks = 4;
2111  	zpy();
2112  	ldx();
2113  }
2114  
2115  OPCODE void op0xB7(void) { //undocumented
2116  	cpu.ticks = 4;
2117  	zpy();
2118  	lax();
2119  }
2120  
2121  OPCODE void op0xB8(void) {
2122  	cpu.ticks = 2;
2123  	imp();
2124  	clv();
2125  }
2126  
2127  OPCODE void op0xB9(void) {
2128  	cpu.ticks = 4;
2129  	absy_t();
2130  	lda();
2131  }
2132  
2133  OPCODE void op0xBA(void) {
2134  	cpu.ticks = 2;
2135  	imp();
2136  	tsx();
2137  }
2138  
2139  OPCODE void op0xBB(void) { //undocumented
2140  	cpu.ticks = 4;
2141  	absy_t();
2142  	las();
2143  }
2144  
2145  OPCODE void op0xBC(void) {
2146  	cpu.ticks = 4;
2147  	absx_t();
2148  	ldy();
2149  }
2150  
2151  OPCODE void op0xBD(void) {
2152  	cpu.ticks = 4;
2153  	absx_t();
2154  	lda();
2155  }
2156  
2157  OPCODE void op0xBE(void) {
2158  	cpu.ticks = 4;
2159  	absy_t();
2160  	ldx();
2161  }
2162  
2163  OPCODE void op0xBF(void) { //undocumented
2164  	cpu.ticks = 4;
2165  	absy_t();
2166  	lax();
2167  }
2168  
2169  OPCODE void op0xC0(void) {
2170  	cpu.ticks = 2;
2171  	imm();
2172  	cpy();
2173  }
2174  
2175  OPCODE void op0xC1(void) {
2176  	cpu.ticks = 6;
2177  	indx();
2178  	cmp();
2179  }
2180  
2181  OPCODE void op0xC2(void) { //nop
2182  	cpu.ticks = 2;
2183  	imm();
2184  }
2185  
2186  OPCODE void op0xC3(void) { //undocumented
2187  	cpu.ticks = 8;
2188  	indx();
2189  	dcp();
2190  }
2191  
2192  OPCODE void op0xC4(void) {
2193  	cpu.ticks = 3;
2194  	zp();
2195  	cpyZP();
2196  }
2197  
2198  OPCODE void op0xC5(void) {
2199  	cpu.ticks = 3;
2200  	zp();
2201  	cmpZP();
2202  }
2203  
2204  OPCODE void op0xC6(void) {
2205  	cpu.ticks = 5;
2206  	zp();
2207  	decZP();
2208  }
2209  
2210  OPCODE void op0xC7(void) { //undocumented
2211  	cpu.ticks = 5;
2212  	zp();
2213  	dcp();
2214  }
2215  
2216  OPCODE void op0xC8(void) {
2217  	cpu.ticks = 2;
2218  	imp();
2219  	iny();
2220  }
2221  
2222  OPCODE void op0xC9(void) {
2223  	cpu.ticks = 2;
2224  	imm();
2225  	cmp();
2226  }
2227  
2228  OPCODE void op0xCA(void) {
2229  	cpu.ticks = 2;
2230  	imp();
2231  	dex();
2232  }
2233  
2234  OPCODE void op0xCB(void) { //undocumented
2235  	cpu.ticks = 2;
2236  	imm();
2237  	axs();
2238  }
2239  
2240  OPCODE void op0xCC(void) {
2241  	cpu.ticks = 4;
2242  	abso();
2243  	cpy();
2244  }
2245  
2246  OPCODE void op0xCD(void) {
2247  	cpu.ticks = 4;
2248  	abso();
2249  	cmp();
2250  }
2251  
2252  OPCODE void op0xCE(void) {
2253  	cpu.ticks = 6;
2254  	abso();
2255  	dec();
2256  }
2257  
2258  OPCODE void op0xCF(void) { //undocumented
2259  	cpu.ticks = 6;
2260  	abso();
2261  	dcp();
2262  }
2263  
2264  OPCODE void op0xD0(void) {
2265  	cpu.ticks = 2;
2266  	rel();
2267  	bne();
2268  }
2269  
2270  OPCODE void op0xD1(void) {
2271  	cpu.ticks = 5;
2272  	indy_t();
2273  	cmp();
2274  }
2275  
2276  OPCODE void op0xD3(void) { //undocumented
2277  	cpu.ticks = 8;
2278  	indy();
2279  	dcp();
2280  }
2281  
2282  OPCODE void op0xD4(void) { //nop
2283  	cpu.ticks = 4;
2284  	zpx();
2285  }
2286  
2287  OPCODE void op0xD5(void) {
2288  	cpu.ticks = 4;
2289  	zpx();
2290  	cmp();
2291  }
2292  
2293  OPCODE void op0xD6(void) {
2294  	cpu.ticks = 6;
2295  	zpx();
2296  	dec();
2297  }
2298  
2299  OPCODE void op0xD7(void) { //undocumented
2300  	cpu.ticks = 6;
2301  	zpx();
2302  	dcp();
2303  }
2304  
2305  OPCODE void op0xD8(void) {
2306  	cpu.ticks = 2;
2307  	imp();
2308  	cld();
2309  }
2310  
2311  OPCODE void op0xD9(void) {
2312  	cpu.ticks = 4;
2313  	absy_t();
2314  	cmp();
2315  }
2316  
2317  OPCODE void op0xDA(void) { //nop
2318  	cpu.ticks = 2;
2319  }
2320  
2321  OPCODE void op0xDB(void) { //undocumented
2322  	cpu.ticks = 7;
2323  	absy();
2324  	dcp();
2325  }
2326  
2327  OPCODE void op0xDC(void) { //nop
2328  	cpu.ticks = 4;
2329  	absx_t();
2330  }
2331  
2332  OPCODE void op0xDD(void) {
2333  	cpu.ticks = 4;
2334  	absx_t();
2335  	cmp();
2336  }
2337  
2338  OPCODE void op0xDE(void) {
2339  	cpu.ticks = 7;
2340  	absx();
2341  	dec();
2342  }
2343  
2344  OPCODE void op0xDF(void) { //undocumented
2345  	cpu.ticks = 7;
2346  	absx();
2347  	dcp();
2348  }
2349  
2350  OPCODE void op0xE0(void) {
2351  	cpu.ticks = 2;
2352  	imm();
2353  	cpx();
2354  }
2355  
2356  OPCODE void op0xE1(void) {
2357  	cpu.ticks = 5;
2358  	indx();
2359  	sbc();
2360  }
2361  
2362  OPCODE void op0xE2(void) { //NOP
2363  	cpu.ticks = 2;
2364  	imm();
2365  }
2366  
2367  OPCODE void op0xE3(void) { //undocumented
2368  	cpu.ticks = 8;
2369  	indx();
2370  	isb();
2371  }
2372  
2373  OPCODE void op0xE4(void) {
2374  	cpu.ticks = 3;
2375  	zp();
2376  	cpxZP();
2377  }
2378  
2379  OPCODE void op0xE5(void) {
2380  	cpu.ticks = 3;
2381  	zp();
2382  	sbcZP();
2383  }
2384  
2385  OPCODE void op0xE6(void) {
2386  	cpu.ticks = 5;
2387  	zp();
2388  	incZP();
2389  }
2390  
2391  OPCODE void op0xE7(void) { //undocumented
2392  	cpu.ticks = 5;
2393  	zp();
2394  	isb();
2395  }
2396  
2397  OPCODE void op0xE8(void) {
2398  	cpu.ticks = 2;
2399  	imp();
2400  	inx();
2401  }
2402  
2403  OPCODE void op0xE9(void) {
2404  	cpu.ticks = 2;
2405  	imm();
2406  	sbc();
2407  }
2408  
2409  OPCODE void op0xEA(void) {
2410  	cpu.ticks = 2;
2411  }
2412  
2413  OPCODE void op0xEB(void) {
2414  	cpu.ticks = 2;
2415  	imm();
2416  	sbc();
2417  }
2418  
2419  OPCODE void op0xEC(void) {
2420  	cpu.ticks = 4;
2421  	abso();
2422  	cpx();
2423  }
2424  
2425  OPCODE void op0xED(void) {
2426  	cpu.ticks = 4;
2427  	abso();
2428  	sbc();
2429  }
2430  
2431  OPCODE void op0xEE(void) {
2432  	cpu.ticks = 6;
2433  	abso();
2434  	inc();
2435  }
2436  
2437  OPCODE void op0xEF(void) { //undocumented
2438  	cpu.ticks = 6;
2439  	abso();
2440  	isb();
2441  }
2442  
2443  OPCODE void op0xF0(void) {
2444  	cpu.ticks = 2;
2445  	rel();
2446  	beq();
2447  }
2448  
2449  OPCODE void op0xF1(void) {
2450  	cpu.ticks = 5;
2451  	indy_t();
2452  	sbc();
2453  }
2454  
2455  OPCODE void op0xF3(void) { //undocumented
2456  	cpu.ticks = 8;
2457  	indy();
2458  	isb();
2459  }
2460  
2461  OPCODE void op0xF4(void) { //nop
2462  	cpu.ticks = 4;
2463  	zpx();
2464  }
2465  
2466  OPCODE void op0xF5(void) {
2467  	cpu.ticks = 4;
2468  	zpx();
2469  	sbc();
2470  }
2471  
2472  OPCODE void op0xF6(void) {
2473  	cpu.ticks = 6;
2474  	zpx();
2475  	inc();
2476  }
2477  
2478  OPCODE void op0xF7(void) { //undocumented
2479  	cpu.ticks = 6;
2480  	zpx();
2481  	isb();
2482  }
2483  
2484  OPCODE void op0xF8(void) {
2485  	cpu.ticks = 2;
2486  	imp();
2487  	sed();
2488  }
2489  
2490  OPCODE void op0xF9(void) {
2491  	cpu.ticks = 4;
2492  	absy_t();
2493  	sbc();
2494  }
2495  
2496  OPCODE void op0xFA(void) { //nop
2497  	cpu.ticks = 2;
2498  }
2499  
2500  OPCODE void op0xFB(void) { //undocumented
2501  	cpu.ticks = 7;
2502  	absy();
2503  	isb();
2504  }
2505  
2506  OPCODE void op0xFC(void) { //nop
2507  	cpu.ticks = 4;
2508  	absx_t();
2509  }
2510  
2511  OPCODE void op0xFD(void) {
2512  	cpu.ticks = 4;
2513  	absx_t();
2514  	sbc();
2515  }
2516  
2517  OPCODE void op0xFE(void) {
2518  	cpu.ticks = 7;
2519  	absx();
2520  	inc();
2521  }
2522  
2523  OPCODE void op0xFF(void) { //undocumented
2524  	cpu.ticks = 7;
2525  	absx();
2526  	isb();
2527  }
2528  
2529  OPCODE void opPATCHD2(void) {
2530  #if APPLY_PATCHES
2531  	patchLOAD();
2532  #else
2533  	opKIL();
2534  #endif
2535  }
2536  
2537  OPCODE void opPATCHF2(void) {
2538  #if APPLY_PATCHES
2539  	patchSAVE();
2540  #else
2541  	opKIL();
2542  #endif
2543  }
2544  
2545  typedef void (*op_ptr_t)( void );
2546  
2547  static const op_ptr_t opcodetable[256] = {
2548    /*        	0   	1   	2   	3   	4   	5   	6   	7   	8	   9   		A   	B   	C   	D   	E   	F */
2549    /* 0  */    op0x0 , op0x1,  opKIL , op0x3,  op0x4 , op0x5,  op0x6,  op0x7,  op0x8,  op0x9,  op0xA,  op0xB , op0xC , op0xD , op0xE , op0xF,
2550    /* 1  */    op0x10, op0x11, opKIL , op0x13, op0x14, op0x15, op0x16, op0x17, op0x18, op0x19, op0x1A, op0x1B, op0x1C, op0x1D, op0x1E, op0x1F,
2551    /* 2  */    op0x20, op0x21, opKIL , op0x23, op0x24, op0x25, op0x26, op0x27, op0x28, op0x29, op0x2A, op0x2B, op0x2C, op0x2D, op0x2E, op0x2F,
2552    /* 3  */    op0x30, op0x31, opKIL , op0x33, op0x34, op0x35, op0x36, op0x37, op0x38, op0x39, op0x3A, op0x3B, op0x3C, op0x3D, op0x3E, op0x3F,
2553    /* 4  */    op0x40, op0x41, opKIL , op0x43, op0x44, op0x45, op0x46, op0x47, op0x48, op0x49, op0x4A, op0x4B, op0x4C, op0x4D, op0x4E, op0x4F,
2554    /* 5  */    op0x50, op0x51, opKIL , op0x53, op0x54, op0x55, op0x56, op0x57, op0x58, op0x59, op0x5A, op0x5B, op0x5C, op0x5D, op0x5E, op0x5F,
2555    /* 6  */    op0x60, op0x61, opKIL , op0x63, op0x64, op0x65, op0x66, op0x67, op0x68, op0x69, op0x6A, op0x6B, op0x6C, op0x6D, op0x6E, op0x6F,
2556    /* 7  */    op0x70, op0x71, opKIL , op0x73, op0x74, op0x75, op0x76, op0x77, op0x78, op0x79, op0x7A, op0x7B, op0x7C, op0x7D, op0x7E, op0x7F,
2557    /* 8  */    op0x80, op0x81, op0x82, op0x83, op0x84, op0x85, op0x86, op0x87, op0x88, op0x89, op0x8A, op0x8B, op0x8C, op0x8D, op0x8E, op0x8F,
2558    /* 9  */    op0x90, op0x91, opKIL , op0x93, op0x94, op0x95, op0x96, op0x97, op0x98, op0x99, op0x9A, op0x9B, op0x9C, op0x9D, op0x9E, op0x9F,
2559    /* A  */    op0xA0, op0xA1, op0xA2, op0xA3, op0xA4, op0xA5, op0xA6, op0xA7, op0xA8, op0xA9, op0xAA, op0xAB, op0xAC, op0xAD, op0xAE, op0xAF,
2560    /* B  */    op0xB0, op0xB1, opKIL , op0xB3, op0xB4, op0xB5, op0xB6, op0xB7, op0xB8, op0xB9, op0xBA, op0xBB, op0xBC, op0xBD, op0xBE, op0xBF,
2561    /* C  */    op0xC0, op0xC1, op0xC2, op0xC3, op0xC4, op0xC5, op0xC6, op0xC7, op0xC8, op0xC9, op0xCA, op0xCB, op0xCC, op0xCD, op0xCE, op0xCF,
2562    /* D  */    op0xD0, op0xD1, opPATCHD2 , op0xD3, op0xD4, op0xD5, op0xD6, op0xD7, op0xD8, op0xD9, op0xDA, op0xDB, op0xDC, op0xDD, op0xDE, op0xDF,
2563    /* E  */    op0xE0, op0xE1, op0xE2, op0xE3, op0xE4, op0xE5, op0xE6, op0xE7, op0xE8, op0xE9, op0xEA, op0xEB, op0xEC, op0xED, op0xEE, op0xEF,
2564    /* F  */    op0xF0, op0xF1, opPATCHF2 , op0xF3, op0xF4, op0xF5, op0xF6, op0xF7, op0xF8, op0xF9, op0xFA, op0xFB, op0xFC, op0xFD, op0xFE, op0xFF
2565  };
2566  
2567  static const uint8_t cyclesTable[256] =
2568  {
2569  	7, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 4, 4, 6, 6,  // $00
2570  	2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 5, 5, 7, 7,  // $10
2571  	6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 4, 4, 6, 6,  // $20
2572  	2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 5, 5, 7, 7,  // $30
2573  	6, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 3, 4, 6, 6,  // $40
2574  	2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 5, 5, 7, 7,  // $50
2575  	6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 5, 4, 6, 6,  // $60
2576  	2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 5, 5, 7, 7,  // $70
2577  	2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4,  // $80
2578  	2, 6, 2, 6, 4, 4, 4, 4, 2, 5, 2, 5, 5, 5, 5, 5,  // $90
2579  	2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4,  // $A0
2580  	2, 5, 2, 5, 4, 4, 4, 4, 2, 4, 2, 5, 4, 4, 4, 4,  // $B0
2581  	2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6,  // $C0
2582  	2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 5, 5, 7, 7,  // $D0
2583  	2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6,  // $E0
2584  	2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 5, 5, 7, 7   // $F0
2585  };
2586  
2587  static const uint8_t writeCycleTable[256] =
2588  {
2589      3, 0, 0, 2, 0, 0, 2, 2, 1, 0, 0, 0, 0, 0, 2, 2, // $00
2590      0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 2, 2, // $10
2591      2, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, // $20
2592      0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 2, 2, // $30
2593      0, 0, 0, 2, 0, 0, 2, 2, 1, 0, 0, 0, 0, 0, 2, 2, // $40
2594      0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 2, 2, // $50
2595      0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, // $60
2596      0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 2, 2, // $70
2597      0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, // $80
2598      0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, // $90
2599      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // $A0
2600      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // $B0
2601      0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, // $C0
2602      0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 2, 2, // $D0
2603      0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, // $E0
2604      0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 2, 2  // $F0
2605  };
2606  
2607  
2608  void cpu_nmi() {
2609    cpu.nmiLine = 1;
2610    printf("nmiLine=1\n");
2611  }
2612  void cpu_clearNmi() {
2613  	cpu.nmi = 0;
2614  }
2615  
2616  void cpu_nmi_do() {
2617  	if (cpu.nmi) return;
2618  	cpu.nmi = 1;
2619  	cpu.nmiLine = 0;
2620  	push16(cpu.pc);
2621  	push8(cpu.cpustatus & ~FLAG_BREAK);
2622  	cpu.cpustatus |= FLAG_INTERRUPT;
2623  	cpu.pc = read6502(0xFFFA) | (read6502(0xFFFB) << 8);
2624  	cpu.ticks = 7;
2625  }
2626  
2627  static inline void cpu_irq() {
2628    push16(cpu.pc);
2629    push8(cpu.cpustatus & ~FLAG_BREAK);
2630    cpu.cpustatus |= FLAG_INTERRUPT;
2631    cpu.pc = read6502(0xFFFE) | (read6502(0xFFFF) << 8);
2632    cpu.ticks = 7;
2633  }
2634  
2635  inline void cia_clock(void)  __attribute__((always_inline));
2636  
2637  void cia_clock(void) {
2638  	cia1_clock(1);
2639  	cia2_clock(1);
2640  }
2641  
2642  void cia_clockt(int ticks) {
2643  	cia1_clock(ticks);
2644  	cia2_clock(ticks);
2645  }
2646  
2647  void cpu_clock(int cycles) {
2648  static int c = 0;
2649  static int writeCycles = 0;
2650  	cpu.lineCyclesAbs += cycles;
2651      c+=cycles;
2652  	while (c > 0) {
2653  
2654  			uint8_t opcode ;
2655  			cpu.ticks = 0;
2656  
2657  			//NMI
2658  
2659  			if (!cpu.nmi && ((cpu.cia2.R[0x0D] & 0x80) | cpu.nmiLine)) {
2660  				cpu_nmi_do();
2661  				goto noOpcode;
2662  			}
2663  
2664  		    if (!(cpu.cpustatus & FLAG_INTERRUPT)) {
2665  				if (((cpu.vic.R[0x19] | cpu.cia1.R[0x0D]) & 0x80)) {
2666  					cpu_irq();
2667  					goto noOpcode;
2668  				}
2669  			}
2670  
2671  			cpu.cpustatus |= FLAG_CONSTANT;
2672  			opcode = read6502(cpu.pc++);
2673  			opcodetable[opcode]();
2674  			writeCycles = writeCycleTable[opcode];
2675  noOpcode:
2676  
2677  			cia_clockt(cpu.ticks);
2678  			c-= cpu.ticks;
2679  			cpu.lineCycles += cpu.ticks;
2680  
2681  			if (cpu.exactTiming) {
2682  				uint32_t t = cpu.lineCycles * MCU_C64_RATIO;
2683  				//while (ARM_DWT_CYCCNT - cpu.lineStartTime < t){;}
2684  			}
2685  
2686  	};
2687  
2688  	return;
2689  }
2690  
2691  //Enable "ExactTiming" Mode
2692  void cpu_setExactTiming() {
2693  	if (!cpu.exactTiming) {
2694  		//enable exact timing
2695  		setAudioOff();
2696  		vic_displaySimpleModeScreen();
2697  
2698  	}
2699  	cpu.exactTiming = 1;
2700  	//cpu.exactTimingStartTime = ARM_DWT_CYCCNT;
2701  	cpu.exactTiming = 0;
2702  }
2703  
2704  //Disable "ExactTiming" Mode
2705  void cpu_disableExactTiming() {
2706      cpu.exactTiming = 0;
2707      setAudioOn();
2708  }
2709  
2710  void cpu_reset() {
2711    enableCycleCounter();
2712    cpu.exactTiming = 0;
2713    cpu.nmi = 0;
2714    cpu.cpustatus = FLAG_CONSTANT;
2715    cpu.pc = read6502(0xFFFC) | (read6502(0xFFFD) << 8);
2716    cpu.sp = 0xFD;
2717  }