/**
* @fileoverview Implements PC6502 opcode handlers.
* @author Jeff Parsons
* @copyright Jeff Parsons 2012-2016
*
* This file is part of PCjs, a computer emulation software project at .
*
* PCjs 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 3
* of the License, or (at your option) any later version.
*
* PCjs 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 PCjs. If not,
* see .
*
* You are required to include the above copyright notice in every source code file of every
* copy or modified version of this work, and to display that copyright notice on every screen
* that loads or runs any version of this software (see COPYRIGHT in /modules/shared/lib/defines.js).
*
* Some PCjs files also attempt to load external resource files, such as character-image files,
* ROM files, and disk image files. Those external resource files are not considered part of PCjs
* for purposes of the GNU General Public License, and the author does not claim any copyright
* as to their contents.
*/
"use strict";
if (NODE) {
var str = require("../../shared/lib/strlib");
var Messages = require("./messages");
var CPUDef = require("./CPUDef");
}
/**
* @this {CPUState}
*/
CPUDef.opBRK = function()
{ // opcode 0x00
// PC++;
this.regPC++;
// STACK(S--) = PCH;
this.abMem[this.regS--] = (this.regPC >> 8);
this.regS |= 0x100;
// STACK(S--) = PCL;
this.abMem[this.regS--] = (this.regPC & 0xff);
this.regS |= 0x100;
// B = 1;
this.regP |= 0x10;
// C = LAZY_C; Z = LAZY_Z; V = LAZY_V; N = LAZY_N;
this.regP = this.getRegP();
// STACK(S--) = P;
this.abMem[this.regS--] = this.regP;
this.regS |= 0x100;
// B = 0;
this.regP &= 0xef;
// EA = 0xFFFE;
this.regEA = 0xFFFE;
// PC = M;
this.regPC = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8));
};
/**
* @this {CPUState}
*/
CPUDef.opORAindx = function()
{ // opcode 0x01
// EA = WORD((BYTE(PC++)+X) & 0xff);
this.regEA = ((this.abMem[this.regPC++]) + this.regX) & 0xff;
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8));
// A = A | ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA |= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opORAzp = function()
{ // opcode 0x05
// EA = BYTE(PC++);
this.regEA = this.abMem[this.regPC++];
// A = A | ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA |= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opASLzp = function()
{ // opcode 0x06
// EA = BYTE(PC++);
this.regEAWrite = this.abMem[this.regPC++];
// RC = ML << 1;
this.regRC = this.abMem[this.regEAWrite] << 1;
// ML = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = (this.regRC & 0xff);
};
/**
* @this {CPUState}
*/
CPUDef.opPHP = function()
{ // opcode 0x08
this.regP = this.getRegP();
// STACK(S--) = P;
this.abMem[this.regS--] = this.regP;
this.regS |= 0x100;
};
/**
* @this {CPUState}
*/
CPUDef.opORAimm = function()
{ // opcode 0x09
// EA = PC++;
this.regEA = this.regPC++;
// A = A | ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA |= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opASLacc = function()
{ // opcode 0x0a
// RC = A << 1;
this.regRC = this.regA << 1;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
};
/**
* @this {CPUState}
*/
CPUDef.opORAabs = function()
{ // opcode 0x0d
// EA = WORD(PC); PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// A = A | ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA |= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opASLabs = function()
{ // opcode 0x0e
// EA = WORD(PC); PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// RC = ML << 1;
this.regRC = this.abMem[this.regEAWrite] << 1;
// ML = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = (this.regRC & 0xff);
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opBPL = function()
{ // opcode 0x10
// PC = PC + (LAZY_N == 0? SBYTE(PC) : 0) + 1;
this.regPC += (!(this.regRN & 0x80)? (this.nStepCycles--,((this.abMem[this.regPC] << 24) >> 24)) : 0) + 1;
};
/**
* @this {CPUState}
*/
CPUDef.opORAindy = function()
{ // opcode 0x11
// EA = WORD(BYTE(PC++))+Y;
this.regEA = (this.abMem[this.regPC++]);
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8)) + this.regY;
// A = A | ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA |= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opORAzpx = function()
{ // opcode 0x15
// EA = (BYTE(PC++)+X) & 0xff;
this.regEA = (this.abMem[this.regPC++]+this.regX) & 0xff;
// A = A | ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA |= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opASLzpx = function()
{ // opcode 0x16
// EA = (BYTE(PC++)+X) & 0xff;
this.regEAWrite = (this.abMem[this.regPC++]+this.regX) & 0xff;
// RC = ML << 1;
this.regRC = this.abMem[this.regEAWrite] << 1;
// ML = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = (this.regRC & 0xff);
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opCLC = function()
{ // opcode 0x18
// SET_LAZY_C(0);
this.regRC = 0x00;
};
/**
* @this {CPUState}
*/
CPUDef.opORAabsy = function()
{ // opcode 0x19
// EA = WORD(PC)+Y; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regY;
// A = A | ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = this.regA |= this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opORAabsx = function()
{ // opcode 0x1d
// EA = WORD(PC)+X; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// A = A | ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = this.regA |= this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opASLabsx = function()
{ // opcode 0x1e
// EA = WORD(PC)+X; PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// RC = ML << 1;
this.regRC = this.abMem[this.regEAWrite] << 1;
// ML = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = (this.regRC & 0xff);
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opJSRabs = function()
{ // opcode 0x20
// EA = PC; PC += 1;
this.regEA = this.regPC++;
// STACK(S--) = PCH;
this.abMem[this.regS--] = (this.regPC >> 8);
this.regS |= 0x100;
// STACK(S--) = PCL;
this.abMem[this.regS--] = (this.regPC & 0xff);
this.regS |= 0x100;
// PC = M;
this.regPC = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8));
};
/**
* @this {CPUState}
*/
CPUDef.opANDindx = function()
{ // opcode 0x21
// EA = WORD((BYTE(PC++)+X) & 0xff);
this.regEA = ((this.abMem[this.regPC++]) + this.regX) & 0xff;
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8));
// A = A & ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA &= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opBITzp = function()
{ // opcode 0x24
// EA = BYTE(PC++);
this.regEA = this.abMem[this.regPC++];
// SET_LAZY_Z((A & ML) == 0);
this.regRZ = (this.regA & this.abMem[this.regEA]);
// SET_LAZY_N(ML7);
this.regRN = ((this.regRN & 0x7f) | (this.abMem[this.regEA] & 0x80));
// SET_LAZY_V(ML6);
this.regRV = 0; this.regRU = ((this.abMem[this.regEA] & 0x40)? 0x80 : 0x00);
};
/**
* @this {CPUState}
*/
CPUDef.opANDzp = function()
{ // opcode 0x25
// EA = BYTE(PC++);
this.regEA = this.abMem[this.regPC++];
// A = A & ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA &= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opROLzp = function()
{ // opcode 0x26
// EA = BYTE(PC++);
this.regEAWrite = this.abMem[this.regPC++];
// RCL = ML;
this.regRC = ((this.regRC & 0xff00) | this.abMem[this.regEAWrite]);
// RC = RC << 1;
this.regRC <<= 1;
// RCL0 = RCH1;
this.regRC = ((this.regRC & 0xfffe) | (((this.regRC & 0x0200))? 0x0001 : 0));
// ML = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = (this.regRC & 0xff);
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opPLP = function()
{ // opcode 0x28
// P = STACK(++S);
this.regS = ((this.regS+1) & 0xff) | 0x100;
this.regP = this.abMem[this.regS];
// SET_LAZY_C(C);
this.regRC = ((this.regP & 0x01)? 0x0100 : 0);
// SET_LAZY_Z(Z);
this.regRZ = (!(this.regP & 0x02)? 0x01 : 0);
// SET_LAZY_N(N);
this.regRN = (this.regP & 0x80);
// SET_LAZY_V(V);
this.regRV = 0; this.regRU = ((this.regP & 0x40)? 0x80 : 0x00);
};
/**
* @this {CPUState}
*/
CPUDef.opANDimm = function()
{ // opcode 0x29
// EA = PC++;
this.regEA = this.regPC++;
// A = A & ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA &= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opROLacc = function()
{ // opcode 0x2a
// RCL = A;
this.regRC = ((this.regRC & 0xff00) | this.regA);
// RC = RC << 1;
this.regRC <<= 1;
// RCL0 = RCH1;
this.regRC = ((this.regRC & 0xfffe) | ((this.regRC & 0x0200)? 0x0001 : 0));
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
};
/**
* @this {CPUState}
*/
CPUDef.opBITabs = function()
{ // opcode 0x2c
// EA = WORD(PC); PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// SET_LAZY_Z((A & ML) == 0);
this.regRZ = (this.regA & this.abMem[this.regEA]);
// SET_LAZY_N(ML7);
this.regRN = ((this.regRN & 0x7f) | (this.abMem[this.regEA] & 0x80));
// SET_LAZY_V(ML6);
this.regRV = 0; this.regRU = ((this.abMem[this.regEA] & 0x40)? 0x80 : 0x00);
};
/**
* @this {CPUState}
*/
CPUDef.opANDabs = function()
{ // opcode 0x2d
// EA = WORD(PC); PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// A = A & ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA &= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opROLabs = function()
{ // opcode 0x2e
// EA = WORD(PC); PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// RCL = ML;
this.regRC = ((this.regRC & 0xff00) | this.abMem[this.regEAWrite]);
// RC = RC << 1;
this.regRC <<= 1;
// RCL0 = RCH1;
this.regRC = ((this.regRC & 0xfffe) | (((this.regRC & 0x0200))? 0x0001 : 0));
// ML = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = (this.regRC & 0xff);
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opBMI = function()
{ // opcode 0x30
// PC = PC + (LAZY_N != 0? SBYTE(PC) : 0) + 1;
this.regPC += ((this.regRN & 0x80)? (this.nStepCycles--,((this.abMem[this.regPC] << 24) >> 24)) : 0) + 1;
};
/**
* @this {CPUState}
*/
CPUDef.opANDindy = function()
{ // opcode 0x31
// EA = WORD(BYTE(PC++))+Y;
this.regEA = (this.abMem[this.regPC++]);
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8)) + this.regY;
// A = A & ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA &= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opANDzpx = function()
{ // opcode 0x35
// EA = (BYTE(PC++)+X) & 0xff;
this.regEA = (this.abMem[this.regPC++]+this.regX) & 0xff;
// A = A & ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA &= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opROLzpx = function()
{ // opcode 0x36
// EA = (BYTE(PC++)+X) & 0xff;
this.regEAWrite = (this.abMem[this.regPC++]+this.regX) & 0xff;
// RCL = ML;
this.regRC = ((this.regRC & 0xff00) | this.abMem[this.regEAWrite]);
// RC = RC << 1;
this.regRC <<= 1;
// RCL0 = RCH1;
this.regRC = ((this.regRC & 0xfffe) | (((this.regRC & 0x0200))? 0x0001 : 0));
// ML = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = (this.regRC & 0xff);
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opSEC = function()
{ // opcode 0x38
// SET_LAZY_C(1);
this.regRC = 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opANDabsy = function()
{ // opcode 0x39
// EA = WORD(PC)+Y; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regY;
// A = A & ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA &= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opANDabsx = function()
{ // opcode 0x3d
// EA = WORD(PC)+X; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// A = A & ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA &= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opROLabsx = function()
{ // opcode 0x3e
// EA = WORD(PC)+X; PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// RCL = ML;
this.regRC = ((this.regRC & 0xff00) | this.abMem[this.regEAWrite]);
// RC = RC << 1;
this.regRC <<= 1;
// RCL0 = RCH1;
this.regRC = ((this.regRC & 0xfffe) | (((this.regRC & 0x0200))? 0x0001 : 0));
// ML = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = (this.regRC & 0xff);
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opRTI = function()
{ // opcode 0x40
// P = STACK(++S);
this.regS = ((this.regS+1) & 0xff) | 0x100;
this.regP = this.abMem[this.regS];
// SET_LAZY_C(C);
this.regRC = ((this.regP & 0x01)? 0x0100 : 0);
// SET_LAZY_Z(Z);
this.regRZ = (!(this.regP & 0x02)? 0x01 : 0);
// SET_LAZY_N(N);
this.regRN = (this.regP & 0x80);
// SET_LAZY_V(V);
this.regRV = 0; this.regRU = ((this.regP & 0x40)? 0x80 : 0x00);
// PCL = STACK(++S);
// PCH = STACK(++S);
this.regS = ((this.regS+2) & 0xff) | 0x100;
this.regPC = (this.abMem[(this.regS-1) | 0x100]) | (this.abMem[this.regS] << 8);
};
/**
* @this {CPUState}
*/
CPUDef.opEORindx = function()
{ // opcode 0x41
// EA = WORD((BYTE(PC++)+X) & 0xff);
this.regEA = ((this.abMem[this.regPC++]) + this.regX) & 0xff;
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8));
// A = A ^ ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA ^= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opEORzp = function()
{ // opcode 0x45
// EA = BYTE(PC++);
this.regEA = this.abMem[this.regPC++];
// A = A ^ ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA ^= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opLSRzp = function()
{ // opcode 0x46
// EA = BYTE(PC++);
this.regEAWrite = this.abMem[this.regPC++];
// SET_LAZY_C(ML0);
this.regRC = ((this.regRC & 0xfeff) | ((this.abMem[this.regEAWrite] & 0x01)? 0x0100 : 0));
// ML = RCL = ML >> 1;
this.abMem[this.regEAWrite] = ((this.regRC = ((this.regRC & 0xff00) | (this.abMem[this.regEAWrite] >> 1))) & 0xff);
// SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = (this.regRC & 0xff);
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opPHA = function()
{ // opcode 0x48
// STACK(S--) = A;
this.abMem[this.regS--] = this.regA;
this.regS |= 0x100;
};
/**
* @this {CPUState}
*/
CPUDef.opEORimm = function()
{ // opcode 0x49
// EA = PC++;
this.regEA = this.regPC++;
// A = A ^ ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA ^= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opLSRacc = function()
{ // opcode 0x4a
// SET_LAZY_C( A0);
this.regRC = ((this.regRC & 0xfeff) | ((this.regA & 0x01)? 0x0100 : 0));
// A = RCL = A >> 1;
this.regA = ((this.regRC = ((this.regRC & 0xff00) | (this.regA >> 1))) & 0xff);
// SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = (this.regRC & 0xff);
};
/**
* @this {CPUState}
*/
CPUDef.opJMPimm16 = function()
{ // opcode 0x4c
// EA = PC;
this.regEA = this.regPC;
// PC += 2;
// this.regPC += 2;
// PC = M;
this.regPC = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8));
};
/**
* @this {CPUState}
*/
CPUDef.opEORabs = function()
{ // opcode 0x4d
// EA = WORD(PC); PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// A = A ^ ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA ^= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opLSRabs = function()
{ // opcode 0x4e
// EA = WORD(PC); PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// SET_LAZY_C(ML0);
this.regRC = ((this.regRC & 0xfeff) | ((this.abMem[this.regEAWrite] & 0x01)? 0x0100 : 0));
// ML = RCL = ML >> 1;
this.abMem[this.regEAWrite] = ((this.regRC = ((this.regRC & 0xff00) | (this.abMem[this.regEAWrite] >> 1))) & 0xff);
// SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = (this.regRC & 0xff);
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opBVC = function()
{ // opcode 0x50
// PC = PC + (LAZY_V == 0? SBYTE(PC) : 0) + 1;
this.regPC += (!((((this.regRV & 0xff) ^ this.regRU) ^ (this.regRV >> 1)) & 0x80)? (this.nStepCycles--,((this.abMem[this.regPC] << 24) >> 24)) : 0) + 1;
};
/**
* @this {CPUState}
*/
CPUDef.opEORindy = function()
{ // opcode 0x51
// EA = WORD(BYTE(PC++))+Y;
this.regEA = this.abMem[this.regPC++];
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8)) + this.regY;
// A = A ^ ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA ^= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opEORzpx = function()
{ // opcode 0x55
// EA = (BYTE(PC++)+X) & 0xff;
this.regEA = (this.abMem[this.regPC++]+this.regX) & 0xff;
// A = A ^ ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA ^= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opLSRzpx = function()
{ // opcode 0x56
// EA = (BYTE(PC++)+X) & 0xff;
this.regEAWrite = (this.abMem[this.regPC++]+this.regX) & 0xff;
// SET_LAZY_C(ML0);
this.regRC = ((this.regRC & 0xfeff) | ((this.abMem[this.regEAWrite] & 0x01)? 0x0100 : 0));
// ML = RCL = ML >> 1;
this.abMem[this.regEAWrite] = ((this.regRC = ((this.regRC & 0xff00) | (this.abMem[this.regEAWrite] >> 1))) & 0xff);
// SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = (this.regRC & 0xff);
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opCLI = function()
{ // opcode 0x58
// I = 0;
this.regP &= 0xfb;
};
/**
* @this {CPUState}
*/
CPUDef.opEORabsy = function()
{ // opcode 0x59
// EA = WORD(PC)+Y; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regY;
// A = A ^ ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = (this.regA ^= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opEORabsx = function()
{ // opcode 0x5d
// EA = WORD(PC)+X; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// A = A ^ ML; SET_LAZY_NZ(A)
this.regRN = this.regRZ = (this.regA ^= this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opLSRabsx = function()
{ // opcode 0x5e
// EA = WORD(PC)+X; PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// SET_LAZY_C(ML0);
this.regRC = ((this.regRC & 0xfeff) | ((this.abMem[this.regEAWrite] & 0x01)? 0x0100 : 0));
// ML = RCL = ML >> 1;
this.abMem[this.regEAWrite] = ((this.regRC = ((this.regRC & 0xff00) | (this.abMem[this.regEAWrite] >> 1))) & 0xff);
// SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = (this.regRC & 0xff);
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opRTS = function()
{ // opcode 0x60
// PCL = STACK(++S);
// PCH = STACK(++S);
// PC++;
this.regS = ((this.regS+2) & 0xff) | 0x100;
this.regPC = (((this.abMem[(this.regS-1) | 0x100])) | ((this.abMem[this.regS]) << 8)) + 1;
};
/**
* @this {CPUState}
*/
CPUDef.opADCindx = function()
{ // opcode 0x61
// EA = WORD((BYTE(PC++)+X) & 0xff);
this.regEA = ((this.abMem[this.regPC++]) + this.regX) & 0xff;
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8));
// RC = (A + ML + LAZY_C);
this.regRC = (this.regA + this.abMem[this.regEA] + ((this.regRC & 0x0100)? 1 : 0));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
};
/**
* @this {CPUState}
*/
CPUDef.opADCindxBCD = function()
{ // opcode 0x61
// EA = WORD((BYTE(PC++)+X) & 0xff);
this.regEA = ((this.abMem[this.regPC++]) + this.regX) & 0xff;
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8));
// A = this.addBCD(A,ML);
this.regA = this.addBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opADCzp = function()
{ // opcode 0x65
// EA = BYTE(PC++);
this.regEA = this.abMem[this.regPC++];
// RC = (A + ML + LAZY_C);
this.regRC = (this.regA + this.abMem[this.regEA] + ((this.regRC & 0x0100)? 1 : 0));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
};
/**
* @this {CPUState}
*/
CPUDef.opADCzpBCD = function()
{ // opcode 0x65
// EA = BYTE(PC++);
this.regEA = this.abMem[this.regPC++];
// A = this.addBCD(A,ML);
this.regA = this.addBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opRORzp = function()
{ // opcode 0x66
// EA = BYTE(PC++);
this.regEAWrite = this.abMem[this.regPC++];
// RCL = ML;
this.regRC = ((this.regRC & 0xff00) | this.abMem[this.regEAWrite]);
// RCH1 = RCL0;
this.regRC = ((this.regRC & 0xfdff) | ((this.regRC & 0x0001)? 0x0200 : 0));
// RC = RC >> 1;
this.regRC >>= 1;
// ML = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = (this.regRC & 0xff);
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opPLA = function()
{ // opcode 0x68
// A = STACK(++S); SET_LAZY_NZ(A);
this.regS = ((this.regS+1) & 0xff) | 0x100;
this.regRN = this.regRZ = this.regA = this.abMem[this.regS];
};
/**
* @this {CPUState}
*/
CPUDef.opADCimm = function()
{ // opcode 0x69
// EA = PC++;
this.regEA = this.regPC++;
// RC = (A + ML + LAZY_C);
this.regRC = (this.regA + this.abMem[this.regEA] + ((this.regRC & 0x0100)? 1 : 0));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
};
/**
* @this {CPUState}
*/
CPUDef.opADCimmBCD = function()
{ // opcode 0x69
// EA = PC++;
this.regEA = this.regPC++;
// A = this.addBCD(A,ML);
this.regA = this.addBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opRORacc = function()
{ // opcode 0x6a
// RCL = A;
this.regRC = ((this.regRC & 0xff00) | this.regA);
// RCH1 = RCL0;
this.regRC = ((this.regRC & 0xfdff) | ((this.regRC & 0x0001)? 0x0200 : 0));
// RC = RC >> 1;
this.regRC >>= 1;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
};
/**
* @this {CPUState}
*
* NOTE from Wikipedia: "The 6502's memory indirect jump instruction, JMP (), is partially broken.
* If is hex xxFF (i.e., any word ending in FF), the processor will not jump to the address stored in xxFF and xxFF+1 as expected,
* but rather the one defined by xxFF and xx00. This defect continued through the entire NMOS line, but was corrected in the CMOS derivatives."
*/
CPUDef.opJMPabs16 = function()
{ // opcode 0x6c
// EA = WORD(PC); PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// PC = M;
this.regPC = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8));
};
/**
* @this {CPUState}
*/
CPUDef.opADCabs = function()
{ // opcode 0x6d
// EA = WORD(PC); PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// RC = (A + ML + LAZY_C);
this.regRC =(this.regA + this.abMem[this.regEA] + ((this.regRC & 0x0100)? 1 : 0));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
};
/**
* @this {CPUState}
*/
CPUDef.opADCabsBCD = function()
{ // opcode 0x6d
// EA = WORD(PC); PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// A = this.addBCD(A,ML);
this.regA = this.addBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opRORabs = function()
{ // opcode 0x6e
// EA = WORD(PC); PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// RCL = ML;
this.regRC = ((this.regRC & 0xff00) | this.abMem[this.regEAWrite]);
// RCH1 = RCL0;
this.regRC = ((this.regRC & 0xfdff) | ((this.regRC & 0x0001)? 0x0200 : 0));
// RC = RC >> 1;
this.regRC >>= 1;
// ML = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = (this.regRC & 0xff);
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opBVS = function()
{ // opcode 0x70
// PC = PC + (LAZY_V != 0? SBYTE(PC) : 0) + 1;
this.regPC += (((((this.regRV & 0xff) ^ this.regRU) ^ (this.regRV >> 1)) & 0x80)? (this.nStepCycles--,((this.abMem[this.regPC] << 24) >> 24)) : 0) + 1;
};
/**
* @this {CPUState}
*/
CPUDef.opADCindy = function()
{ // opcode 0x71
// EA = WORD(BYTE(PC++))+Y;
this.regEA = (this.abMem[this.regPC++]);
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8)) + this.regY;
// RC = (A + ML + LAZY_C);
this.regRC = (this.regA + this.abMem[this.regEA] + ((this.regRC & 0x0100)? 1 : 0));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
};
/**
* @this {CPUState}
*/
CPUDef.opADCindyBCD = function()
{ // opcode 0x71
// EA = WORD(BYTE(PC++))+Y;
this.regEA = (this.abMem[this.regPC++]);
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8)) + this.regY;
// A = this.addBCD(A,ML);
this.regA = this.addBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opADCzpx = function()
{ // opcode 0x75
// EA = (BYTE(PC++)+X) & 0xff;
this.regEA = (this.abMem[this.regPC++]+this.regX) & 0xff;
// RC = (A + ML + LAZY_C);
this.regRC = (this.regA + this.abMem[this.regEA] + ((this.regRC & 0x0100)? 1 : 0));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
};
/**
* @this {CPUState}
*/
CPUDef.opADCzpxBCD = function()
{ // opcode 0x75
// EA = (BYTE(PC++)+X) & 0xff;
this.regEA = (this.abMem[this.regPC++]+this.regX) & 0xff;
// A = this.addBCD(A,ML);
this.regA = this.addBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opRORzpx = function()
{ // opcode 0x76
// EA = (BYTE(PC++)+X) & 0xff;
this.regEAWrite = (this.abMem[this.regPC++]+this.regX) & 0xff;
// RCL = ML;
this.regRC = ((this.regRC & 0xff00) | this.abMem[this.regEAWrite]);
// RCH1 = RCL0;
this.regRC = ((this.regRC & 0xfdff) | ((this.regRC & 0x0001)? 0x0200 : 0));
// RC = RC >> 1;
this.regRC >>= 1;
// ML = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = (this.regRC & 0xff);
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opSEI = function()
{ // opcode 0x78
// I = 1;
this.regP |= 0x04;
};
/**
* @this {CPUState}
*/
CPUDef.opADCabsy = function()
{ // opcode 0x79
// EA = WORD(PC)+Y; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regY;
// RC = (A + ML + LAZY_C);
this.regRC = (this.regA + this.abMem[this.regEA] + ((this.regRC & 0x0100)? 1 : 0));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
};
/**
* @this {CPUState}
*/
CPUDef.opADCabsyBCD = function()
{ // opcode 0x79
// EA = WORD(PC)+Y; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regY;
// A = this.addBCD(A,ML);
this.regA = this.addBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opADCabsx = function()
{ // opcode 0x7d
// EA = WORD(PC)+X; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// RC = (A + ML + LAZY_C);
this.regRC = (this.regA + this.abMem[this.regEA] + ((this.regRC & 0x0100)? 1 : 0));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
};
/**
* @this {CPUState}
*/
CPUDef.opADCabsxBCD = function()
{ // opcode 0x7d
// EA = WORD(PC)+X; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// A = this.addBCD(A,ML);
this.regA = this.addBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opRORabsx = function()
{ // opcode 0x7e
// EA = WORD(PC)+X; PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// RCL = ML;
this.regRC = ((this.regRC & 0xff00) | this.abMem[this.regEAWrite]);
// RCH1 = RCL0;
this.regRC = ((this.regRC & 0xfdff) | ((this.regRC & 0x0001)? 0x0200 : 0));
// RC = RC >> 1;
this.regRC >>= 1;
// ML = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = (this.regRC & 0xff);
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opSTAindx = function()
{ // opcode 0x81
// EA = WORD((BYTE(PC++)+X) & 0xff);
this.regEAWrite = ((this.abMem[this.regPC++]) + this.regX) & 0xff;
this.regEAWrite = (this.abMem[this.regEAWrite] | (this.abMem[this.regEAWrite+1] << 8));
// ML = A;
this.abMem[this.regEAWrite] = this.regA;
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opSTYzp = function()
{ // opcode 0x84
// EA = BYTE(PC++);
this.regEAWrite = this.abMem[this.regPC++];
// ML = Y;
this.abMem[this.regEAWrite] = this.regY;
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opSTAzp = function()
{ // opcode 0x85
// EA = BYTE(PC++);
this.regEAWrite = this.abMem[this.regPC++];
// ML = A;
this.abMem[this.regEAWrite] = this.regA;
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opSTXzp = function()
{ // opcode 0x86
// EA = BYTE(PC++);
this.regEAWrite = this.abMem[this.regPC++];
// ML = X;
this.abMem[this.regEAWrite] = this.regX;
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opDEY = function()
{ // opcode 0x88
// Y = ((Y - 1) & 0xff);
this.regY = ((this.regY - 1) & 0xff);
// SET_LAZY_NZ(Y);
this.regRN = this.regRZ = (this.regY);
};
/**
* @this {CPUState}
*/
CPUDef.opTXA = function()
{ // opcode 0x8a
// A = X; SET_LAZY_NZ(X);
this.regRN = this.regRZ = this.regA = this.regX;
};
/**
* @this {CPUState}
*/
CPUDef.opSTYabs = function()
{ // opcode 0x8c
// EA = WORD(PC); PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// ML = Y;
this.abMem[this.regEAWrite] = this.regY;
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opSTAabs = function()
{ // opcode 0x8d
// EA = WORD(PC); PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// ML = A;
this.abMem[this.regEAWrite] = this.regA;
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opSTXabs = function()
{ // opcode 0x8e
// EA = WORD(PC); PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// ML = X;
this.abMem[this.regEAWrite] = this.regX;
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opBCC = function()
{ // opcode 0x90
// PC = PC + (LAZY_C == 0? SBYTE(PC) : 0) + 1;
this.regPC += (!(this.regRC & 0x0100)? (this.nStepCycles--,((this.abMem[this.regPC] << 24) >> 24)) : 0) + 1;
};
/**
* @this {CPUState}
*/
CPUDef.opSTAindy = function()
{ // opcode 0x91
// EA = WORD(BYTE(PC++))+Y;
this.regEAWrite = (this.abMem[this.regPC++]);
this.regEAWrite = (this.abMem[this.regEAWrite] | (this.abMem[this.regEAWrite+1] << 8)) + this.regY;
// ML = A;
this.abMem[this.regEAWrite] = this.regA;
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opSTYzpx = function()
{ // opcode 0x94
// EA = (BYTE(PC++)+X) & 0xff;
this.regEAWrite = (this.abMem[this.regPC++]+this.regX) & 0xff;
// ML = Y;
this.abMem[this.regEAWrite] = this.regY;
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opSTAzpx = function()
{ // opcode 0x95
// EA = (BYTE(PC++)+X) & 0xff;
this.regEAWrite = (this.abMem[this.regPC++]+this.regX) & 0xff;
// ML = A;
this.abMem[this.regEAWrite] = this.regA;
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opSTXzpy = function()
{ // opcode 0x96
// EA = (BYTE(PC++)+Y) & 0xff;
this.regEAWrite = (this.abMem[this.regPC++]+this.regY) & 0xff;
// ML = X;
this.abMem[this.regEAWrite] = this.regX;
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opTYA = function()
{ // opcode 0x98
// A = Y; SET_LAZY_NZ(Y);
this.regRN = this.regRZ = this.regA = this.regY;
};
/**
* @this {CPUState}
*/
CPUDef.opSTAabsy = function()
{ // opcode 0x99
// EA = WORD(PC)+Y; PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regY;
// ML = A;
this.abMem[this.regEAWrite] = this.regA;
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opTXS = function()
{ // opcode 0x9a
// S = X;
this.regS = this.regX | 0x100;
};
/**
* @this {CPUState}
*/
CPUDef.opSTAabsx = function()
{ // opcode 0x9d
// EA = WORD(PC)+X; PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// ML = A;
this.abMem[this.regEAWrite] = this.regA;
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opLDYimm = function()
{ // opcode 0xa0
// EA = PC++;
this.regEA = this.regPC++;
// Y = ML; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.regY = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opLDAindx = function()
{ // opcode 0xa1
// EA = WORD((BYTE(PC++)+X) & 0xff);
this.regEA = ((this.abMem[this.regPC++]) + this.regX) & 0xff;
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8));
// A = ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = this.regA = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opLDXimm = function()
{ // opcode 0xa2
// EA = PC++;
this.regEA = this.regPC++;
// X = ML; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.regX = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opLDYzp = function()
{ // opcode 0xa4
// EA = BYTE(PC++);
this.regEA = this.abMem[this.regPC++];
// Y = ML; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.regY = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opLDAzp = function()
{ // opcode 0xa5
// EA = BYTE(PC++);
this.regEA = this.abMem[this.regPC++];
// A = ML; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.regA = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opLDXzp = function()
{ // opcode 0xa6
// EA = BYTE(PC++);
this.regEA = this.abMem[this.regPC++];
// X = ML; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.regX = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opTAY = function()
{ // opcode 0xa8
// Y = A; SET_LAZY_NZ(A);
this.regRN = this.regRZ = this.regY = this.regA;
};
/**
* @this {CPUState}
*/
CPUDef.opLDAimm = function()
{ // opcode 0xa9
// EA = PC++;
this.regEA = this.regPC++;
// A = ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = this.regA = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opTAX = function()
{ // opcode 0xaa
// X = A; SET_LAZY_NZ(A);
this.regRN = this.regRZ = this.regX = this.regA;
};
/**
* @this {CPUState}
*/
CPUDef.opLDYabs = function()
{ // opcode 0xac
// EA = WORD(PC); PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// Y = ML; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.regY = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opLDAabs = function()
{ // opcode 0xad
// EA = WORD(PC); PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// A = ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = this.regA = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opLDXabs = function()
{ // opcode 0xae
// EA = WORD(PC); PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// X = ML; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.regX = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opBCS = function()
{ // opcode 0xb0
// PC = PC + (LAZY_C != 0? SBYTE(PC) : 0) + 1;
this.regPC += ((this.regRC & 0x0100)? (this.nStepCycles--,((this.abMem[this.regPC] << 24) >> 24)) : 0) + 1;
};
/**
* @this {CPUState}
*/
CPUDef.opLDAindy = function()
{ // opcode 0xb1
// EA = WORD(BYTE(PC++))+Y;
this.regEA = (this.abMem[this.regPC++]);
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8)) + this.regY;
// A = ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = this.regA = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opLDYzpx = function()
{ // opcode 0xb4
// EA = (BYTE(PC++)+X) & 0xff;
this.regEA = (this.abMem[this.regPC++]+this.regX) & 0xff;
// Y = ML; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.regY = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opLDAzpx = function()
{ // opcode 0xb5
// EA = (BYTE(PC++)+X) & 0xff;
this.regEA = (this.abMem[this.regPC++]+this.regX) & 0xff;
// A = ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = this.regA = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opLDXzpy = function()
{ // opcode 0xb6
// EA = (BYTE(PC++)+Y) & 0xff;
this.regEA = (this.abMem[this.regPC++]+this.regY) & 0xff;
// X = ML; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.regX = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opCLV = function()
{ // opcode 0xb8
// SET_LAZY_V(0);
this.regRV = 0; this.regRU = 0;
};
/**
* @this {CPUState}
*/
CPUDef.opLDAabsy = function()
{ // opcode 0xb9
// EA = WORD(PC)+Y; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regY;
// A = ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = this.regA = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opTSX = function()
{ // opcode 0xba
// X = S; SET_LAZY_NZ(S);
this.regRN = this.regRZ = this.regX = this.regS & 0xff;
};
/**
* @this {CPUState}
*/
CPUDef.opLDYabsx = function()
{ // opcode 0xbc
// EA = WORD(PC)+X; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// Y = ML; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.regY = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opLDAabsx = function()
{ // opcode 0xbd
// EA = WORD(PC)+X; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// A = ML; SET_LAZY_NZ(A);
this.regRN = this.regRZ = this.regA = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opLDXabsy = function()
{ // opcode 0xbe
// EA = WORD(PC)+Y; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regY;
// X = ML; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.regX = this.abMem[this.regEA];
};
/**
* @this {CPUState}
*/
CPUDef.opCPYimm = function()
{ // opcode 0xc0
// EA = PC++;
this.regEA = this.regPC++;
// RC = Y - ML;
this.regRC = this.regY - this.abMem[this.regEA];
// SET_LAZY_NZ(RC);
this.regRN = this.regRZ = (this.regRC);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opCMPindx = function()
{ // opcode 0xc1
// EA = WORD((BYTE(PC++)+X) & 0xff);
this.regEA = ((this.abMem[this.regPC++]) + this.regX) & 0xff;
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8));
// RC = A - ML; SET_LAZY_NZ(RC);
this.regRN = this.regRZ = this.regRC = (this.regA - this.abMem[this.regEA]);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opCPYzp = function()
{ // opcode 0xc4
// EA = BYTE(PC++);
this.regEA = this.abMem[this.regPC++];
// RC = Y - ML;
this.regRC = this.regY - this.abMem[this.regEA];
// SET_LAZY_NZ(RC);
this.regRN = this.regRZ = (this.regRC);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opCMPzp = function()
{ // opcode 0xc5
// EA = BYTE(PC++);
this.regEA = this.abMem[this.regPC++];
// RC = A - ML; SET_LAZY_NZ(RC);
this.regRN = this.regRZ = this.regRC = (this.regA - this.abMem[this.regEA]);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opDECzp = function()
{ // opcode 0xc6
// EA = BYTE(PC++);
this.regEAWrite = this.abMem[this.regPC++];
// ML = ML - 1; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = ((this.abMem[this.regEAWrite] - 1) & 0xff);
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opINY = function()
{ // opcode 0xc8
// Y = ((Y + 1) & 0xff);
this.regY = ((this.regY + 1) & 0xff);
// SET_LAZY_NZ(Y);
this.regRN = this.regRZ = (this.regY);
};
/**
* @this {CPUState}
*/
CPUDef.opCMPimm = function()
{ // opcode 0xc9
// EA = PC++;
this.regEA = this.regPC++;
// RC = A - ML; SET_LAZY_NZ(RC);
this.regRN = this.regRZ = this.regRC = (this.regA - this.abMem[this.regEA]);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opDEX = function()
{ // opcode 0xca
// X = ((X - 1) & 0xff); SET_LAZY_NZ(X);
this.regRN = this.regRZ = this.regX = ((this.regX - 1) & 0xff);
};
/**
* @this {CPUState}
*/
CPUDef.opCPYabs = function()
{ // opcode 0xcc
// EA = WORD(PC); PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// RC = Y - ML; SET_LAZY_NZ(RC);
this.regRN = this.regRZ = this.regRC = this.regY - this.abMem[this.regEA];
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opCMPabs = function()
{ // opcode 0xcd
// EA = WORD(PC); PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// RC = A - ML; SET_LAZY_NZ(RC);
this.regRN = this.regRZ = this.regRC = (this.regA - this.abMem[this.regEA]);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opDECabs = function()
{ // opcode 0xce
// EA = WORD(PC); PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// ML = ML - 1; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = ((this.abMem[this.regEAWrite] - 1) & 0xff);
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opBNE = function()
{ // opcode 0xd0
// PC = PC + (LAZY_Z == 0? SBYTE(PC) : 0) + 1;
this.regPC += ((this.regRZ & 0xff)? (this.nStepCycles--,((this.abMem[this.regPC] << 24) >> 24)) : 0) + 1;
};
/**
* @this {CPUState}
*/
CPUDef.opCMPindy = function()
{ // opcode 0xd1
// EA = WORD(BYTE(PC++))+Y;
this.regEA = (this.abMem[this.regPC++]);
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8)) + this.regY;
// RC = A - ML; SET_LAZY_NZ(RC);
this.regRN = this.regRZ = this.regRC = (this.regA - this.abMem[this.regEA]);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opCMPzpx = function()
{ // opcode 0xd5
// EA = (BYTE(PC++)+X) & 0xff;
this.regEA = (this.abMem[this.regPC++]+this.regX) & 0xff;
// RC = A - ML; SET_LAZY_NZ(RC);
this.regRN = this.regRZ = this.regRC = (this.regA - this.abMem[this.regEA]);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opDECzpx = function()
{ // opcode 0xd6
// EA = (BYTE(PC++)+X) & 0xff;
this.regEAWrite = (this.abMem[this.regPC++]+this.regX) & 0xff;
// ML = ML - 1; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = ((this.abMem[this.regEAWrite] - 1) & 0xff);
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opCLD = function()
{ // opcode 0xd8
// D = 0;
this.clearBCD();
};
/**
* @this {CPUState}
*/
CPUDef.opCMPabsy = function()
{ // opcode 0xd9
// EA = WORD(PC)+Y; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regY;
// RC = A - ML; SET_LAZY_NZ(RC);
this.regRN = this.regRZ = this.regRC = (this.regA - this.abMem[this.regEA]);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opCMPabsx = function()
{ // opcode 0xdd
// EA = WORD(PC)+X; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// RC = A - ML; SET_LAZY_NZ(RC);
this.regRN = this.regRZ = this.regRC = (this.regA - this.abMem[this.regEA]);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opDECabsx = function()
{ // opcode 0xde
// EA = WORD(PC)+X; PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// ML = ML - 1; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = ((this.abMem[this.regEAWrite] - 1) & 0xff);
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opCPXimm = function()
{ // opcode 0xe0
// EA = PC++;
this.regEA = this.regPC++;
// RC = X - ML;
this.regRC = this.regX - this.abMem[this.regEA];
// SET_LAZY_NZ(RC);
this.regRN = this.regRZ = (this.regRC);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opSBCindx = function()
{ // opcode 0xe1
// EA = WORD((BYTE(PC++)+X) & 0xff);
this.regEA = ((this.abMem[this.regPC++]) + this.regX) & 0xff;
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8));
// RC = (A - ML - !LAZY_C);
this.regRC = (this.regA - this.abMem[this.regEA] - ((this.regRC & 0x0100)? 0 : 1));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opSBCindxBCD = function()
{ // opcode 0xe1
// EA = WORD((BYTE(PC++)+X) & 0xff);
this.regEA = ((this.abMem[this.regPC++]) + this.regX) & 0xff;
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8));
// A = this.subBCD(A,ML);
this.regA = this.subBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opCPXzp = function()
{ // opcode 0xe4
// EA = BYTE(PC++);
this.regEA = this.abMem[this.regPC++];
// RC = X - ML;
this.regRC = this.regX - this.abMem[this.regEA];
// SET_LAZY_NZ(RC);
this.regRN = this.regRZ = (this.regRC);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opSBCzp = function()
{ // opcode 0xe5
// EA = BYTE(PC++);
this.regEA = this.abMem[this.regPC++];
// RC = (A - ML - !LAZY_C);
this.regRC = (this.regA - this.abMem[this.regEA] - ((this.regRC & 0x0100)? 0 : 1));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opSBCzpBCD = function()
{ // opcode 0xe5
// EA = BYTE(PC++);
this.regEA = this.abMem[this.regPC++];
// A = this.subBCD(A,ML);
this.regA = this.subBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opINCzp = function()
{ // opcode 0xe6
// EA = BYTE(PC++);
this.regEAWrite = this.abMem[this.regPC++];
// ML = ML + 1; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = ((this.abMem[this.regEAWrite] + 1) & 0xff);
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opINX = function()
{ // opcode 0xe8
// X = ((X + 1) & 0xff);
this.regX = ((this.regX + 1) & 0xff);
// SET_LAZY_NZ(X);
this.regRN = this.regRZ = (this.regX);
};
/**
* @this {CPUState}
*/
CPUDef.opSBCimm = function()
{ // opcode 0xe9
// EA = PC++;
this.regEA = this.regPC++;
// RC = (A - ML - !LAZY_C);
this.regRC = (this.regA - this.abMem[this.regEA] - ((this.regRC & 0x0100)? 0 : 1));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opSBCimmBCD = function()
{ // opcode 0xe9
// EA = PC++;
this.regEA = this.regPC++;
// A = this.subBCD(A,ML);
this.regA = this.subBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opNOP = function()
{ // opcode 0xea
//
};
/**
* @this {CPUState}
*/
CPUDef.opCPXabs = function()
{ // opcode 0xec
// EA = WORD(PC); PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// RC = X - ML; SET_LAZY_NZ(RC);
this.regRN = this.regRZ = this.regRC = this.regX - this.abMem[this.regEA];
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opSBCabs = function()
{ // opcode 0xed
// EA = WORD(PC); PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// RC = (A - ML - !LAZY_C);
this.regRC = (this.regA - this.abMem[this.regEA] - ((this.regRC & 0x0100)? 0 : 1));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opSBCabsBCD = function()
{ // opcode 0xed
// EA = WORD(PC); PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// A = this.subBCD(A,ML);
this.regA = this.subBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opINCabs = function()
{ // opcode 0xee
// EA = WORD(PC); PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
// ML = ML + 1; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = ((this.abMem[this.regEAWrite] + 1) & 0xff);
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opBEQ = function()
{ // opcode 0xf0
// PC = PC + (LAZY_Z == 1? SBYTE(PC) : 0) + 1;
this.regPC += (!(this.regRZ & 0xff)? (this.nStepCycles--,((this.abMem[this.regPC] << 24) >> 24)) : 0) + 1;
};
/**
* @this {CPUState}
*/
CPUDef.opSBCindy = function()
{ // opcode 0xf1
// EA = WORD(BYTE(PC++))+Y;
this.regEA = (this.abMem[this.regPC++]);
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8)) + this.regY;
// RC = (A - ML - !LAZY_C);
this.regRC = (this.regA - this.abMem[this.regEA] - ((this.regRC & 0x0100)? 0 : 1));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opSBCindyBCD = function()
{ // opcode 0xf1
// EA = WORD(BYTE(PC++))+Y;
this.regEA = (this.abMem[this.regPC++]);
this.regEA = (this.abMem[this.regEA] | (this.abMem[this.regEA+1] << 8)) + this.regY;
// A = this.subBCD(A,ML);
this.regA = this.subBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opSBCzpx = function()
{ // opcode 0xf5
// EA = (BYTE(PC++)+X) & 0xff;
this.regEA = (this.abMem[this.regPC++]+this.regX) & 0xff;
// RC = (A - ML - !LAZY_C);
this.regRC = (this.regA - this.abMem[this.regEA] - ((this.regRC & 0x0100)? 0 : 1));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opSBCzpxBCD = function()
{ // opcode 0xf5
// EA = (BYTE(PC++)+X) & 0xff;
this.regEA = (this.abMem[this.regPC++]+this.regX) & 0xff;
// A = this.subBCD(A,ML);
this.regA = this.subBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opINCzpx = function()
{ // opcode 0xf6
// EA = (BYTE(PC++)+X) & 0xff;
this.regEAWrite = (this.abMem[this.regPC++]+this.regX) & 0xff;
// ML = ML + 1; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = ((this.abMem[this.regEAWrite] + 1) & 0xff);
// W = 1;
// NOTE: Consider alternatives for tracking zero-page writes (eg, regEAWriteZP)
};
/**
* @this {CPUState}
*/
CPUDef.opSED = function()
{ // opcode 0xf8
// D = 1;
this.setBCD();
};
/**
* @this {CPUState}
*/
CPUDef.opSBCabsy = function()
{ // opcode 0xf9
// EA = WORD(PC)+Y; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regY;
// RC = (A - ML - !LAZY_C);
this.regRC = (this.regA - this.abMem[this.regEA] - ((this.regRC & 0x0100)? 0 : 1));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opSBCabsyBCD = function()
{ // opcode 0xf9
// EA = WORD(PC)+Y; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regY;
// A = this.subBCD(A,ML);
this.regA = this.subBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opSBCabsx = function()
{ // opcode 0xfd
// EA = WORD(PC)+X; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// RC = (A - ML - !LAZY_C);
this.regRC = (this.regA - this.abMem[this.regEA] - ((this.regRC & 0x0100)? 0 : 1));
// SET_LAZY_OV(A,ML,RC);
this.regRU = this.regA ^ this.abMem[this.regEA]; this.regRV = this.regRC;
// A = RCL; SET_LAZY_NZ(RCL);
this.regRN = this.regRZ = this.regA = (this.regRC & 0xff);
// SET_LAZY_C(!LAZY_C);
this.regRC ^= 0x0100;
};
/**
* @this {CPUState}
*/
CPUDef.opSBCabsxBCD = function()
{ // opcode 0xfd
// EA = WORD(PC)+X; PC += 2;
this.regEA = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// A = this.subBCD(A,ML);
this.regA = this.subBCD(this.regA, this.abMem[this.regEA]);
};
/**
* @this {CPUState}
*/
CPUDef.opINCabsx = function()
{ // opcode 0xfe
// EA = WORD(PC)+X; PC += 2;
this.regEAWrite = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8)) + this.regX;
// ML = ML + 1; SET_LAZY_NZ(ML);
this.regRN = this.regRZ = this.abMem[this.regEAWrite] = ((this.abMem[this.regEAWrite] + 1) & 0xff);
// W = 1;
};
/**
* @this {CPUState}
*/
CPUDef.opSim = function()
{
var addr;
var bSimOp = this.abMem[this.regPC++];
switch(bSimOp) {
case this.SIMOP_HLT:
this.println("HALT");
this.halt();
break;
case this.SIMOP_MSG:
addr = this.regPC; // currently we're using "inline" strings
// addr = (this.abMem[this.regPC++] | (this.abMem[this.regPC++] << 8));
var s = "";
while (addr < this.abMem.length) {
var b = this.abMem[addr++];
if (!b) break;
s += String.fromCharCode(b);
}
this.regPC = addr; // update regPC as long as we're doing "inline" strings
/*
* Before simply printing the string, what kinds of handy substitutions should we provide?
*
* eg: %A for this.regA, %X for this.regX, etc
*/
s = s.replace(/%A/g, str.toHex(this.regA, 2)).replace(/%X/g, str.toHex(this.regX, 2)).replace(/%Y/g, str.toHex(this.regY, 2));
this.println(s);
/*
* To make printing "smoother", let's force a yield
*/
this.yieldCPU();
break;
default:
this.regPC -= 2;
this.println("undefined opSim: " + str.toHexByte(bSimOp) + " at " + str.toHexWord(this.regPC));
this.halt();
}
};
/**
* @this {CPUState}
*/
CPUDef.opUndefined = function()
{
var b = this.abMem[--this.regPC];
this.println("undefined opcode: " + str.toHexByte(b) + " at " + str.toHexWord(this.regPC));
this.halt();
};