- Seguim
This commit is contained in:
118
6502m.cpp
118
6502m.cpp
@@ -11,17 +11,6 @@
|
|||||||
#define fV 0b01000000 // Overflow
|
#define fV 0b01000000 // Overflow
|
||||||
#define fN 0b10000000 // Negative
|
#define fN 0b10000000 // Negative
|
||||||
|
|
||||||
// Jump types
|
|
||||||
#define cUnconditional 255
|
|
||||||
#define cNZ 0
|
|
||||||
#define cZ 1
|
|
||||||
#define cNC 2
|
|
||||||
#define cC 3
|
|
||||||
#define cNN 4
|
|
||||||
#define cN 5
|
|
||||||
#define cNV 6
|
|
||||||
#define cV 7
|
|
||||||
|
|
||||||
// Addressing modes
|
// Addressing modes
|
||||||
#define aAccumulator 0
|
#define aAccumulator 0
|
||||||
#define aImmediate 1
|
#define aImmediate 1
|
||||||
@@ -103,6 +92,10 @@ namespace m6502
|
|||||||
miReadAddress,
|
miReadAddress,
|
||||||
miReadAddressAndSkip,
|
miReadAddressAndSkip,
|
||||||
miWriteRegister,
|
miWriteRegister,
|
||||||
|
miWriteAddress,
|
||||||
|
miPushA,
|
||||||
|
miFetchOperandAndCheckBranch,
|
||||||
|
miCheckIfPageCrossed,
|
||||||
miNumMicroinstructions
|
miNumMicroinstructions
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,6 +107,68 @@ namespace m6502
|
|||||||
/* 0x03 --- */ { miFetchOpcode },
|
/* 0x03 --- */ { miFetchOpcode },
|
||||||
/* 0x04 --- */ { miFetchOpcode },
|
/* 0x04 --- */ { miFetchOpcode },
|
||||||
/* 0x05 ORA zpg */ { miFetchOperandLo, miReadAddress, miFetchOpcode },
|
/* 0x05 ORA zpg */ { miFetchOperandLo, miReadAddress, miFetchOpcode },
|
||||||
|
/* 0x06 ASL zpg */ { miFetchOperandLo, miReadAddress, miWriteAddress, miWriteAddress, miFetchOpcode },
|
||||||
|
/* 0x07 --- */ { miFetchOpcode },
|
||||||
|
/* 0x08 PHP */ { miFetchOperandLo, miPushP, miFetchOpcode },
|
||||||
|
/* 0x09 ORA imm */ { miFetchOperandLo, miFetchOpcode },
|
||||||
|
/* 0x0A ASL A */ { miFakeFetchOperand, miFetchOpcode },
|
||||||
|
/* 0x0B --- */ { miFetchOpcode },
|
||||||
|
/* 0x0C --- */ { miFetchOpcode },
|
||||||
|
/* 0x0D ORA abs */ { miFetchOperandLo, miFetchOperandHi, miReadAddress, miFetchOpcode },
|
||||||
|
/* 0x0E ASL abs */ { miFetchOperandLo, miFetchOperandHi, miReadAddress, miWriteAddress, miWriteAddress, miFetchOpcode },
|
||||||
|
/* 0x0F --- */ { miFetchOpcode },
|
||||||
|
|
||||||
|
/* 0x10 BPL */ { miFetchOperandAndCheckBranch, miCheckIfPageCrossed, miFakeFetchOperand, miFetchOpcode },
|
||||||
|
/* 0x11 ORA ind,Y */ { miFetchOperandLo, miFetchAddressLo, miFetchAddressHiAndIndex, miReadAddressAndSkip, miReadAddress, miFetchOpcode },
|
||||||
|
/* 0x12 --- */ { miFetchOpcode },
|
||||||
|
/* 0x13 --- */ { miFetchOpcode },
|
||||||
|
/* 0x14 --- */ { miFetchOpcode },
|
||||||
|
/* 0x15 ORA zpg,X */ { miFetchOperandLo, miIndexX, miReadAddress, miFetchOpcode },
|
||||||
|
/* 0x16 ASL zpg,X */ { miFetchOperandLo, miIndexX, miReadAddress, miWriteAddress, miWriteAddress, miFetchOpcode },
|
||||||
|
/* 0x17 --- */ { miFetchOpcode },
|
||||||
|
/* 0x18 CLC */ { miFetchOperandLo, miFetchOpcode },
|
||||||
|
/* 0x19 ORA abs,Y */ { miFetchOperandLo, miFetchOperandHiAndIndexY, miReadAddressAndSkip, miReadAddress, miFetchOpcode },
|
||||||
|
/* 0x1A --- */ { miFetchOpcode },
|
||||||
|
/* 0x1B --- */ { miFetchOpcode },
|
||||||
|
/* 0x1C --- */ { miFetchOpcode },
|
||||||
|
/* 0x1D ORA abs,X */ { miFetchOperandLo, miFetchOperandHiAndIndexX, miReadAddressAndSkip, miReadAddress, miFetchOpcode },
|
||||||
|
/* 0x1E ASL abs,X */ { miFetchOperandLo, miFetchOperandHiAndIndexX, miReadAddress, miReadAddress, miWriteAddress, miWriteAddress, miFetchOpcode },
|
||||||
|
/* 0x1F --- */ { miFetchOpcode },
|
||||||
|
|
||||||
|
/* 0x20 JSR abs */ { },
|
||||||
|
/* 0x21 ORA X,ind */ { miFetchOperandLo, miIndexX, miFetchAddressLo, miFetchAddressHi, miReadAddress, miFetchOpcode },
|
||||||
|
/* 0x22 --- */ { miFetchOpcode },
|
||||||
|
/* 0x23 --- */ { miFetchOpcode },
|
||||||
|
/* 0x24 --- */ { miFetchOpcode },
|
||||||
|
/* 0x25 ORA zpg */ { miFetchOperandLo, miReadAddress, miFetchOpcode },
|
||||||
|
/* 0x26 ASL zpg */ { miFetchOperandLo, miReadAddress, miWriteAddress, miWriteAddress, miFetchOpcode },
|
||||||
|
/* 0x27 --- */ { miFetchOpcode },
|
||||||
|
/* 0x28 PHP */ { miFetchOperandLo, miPushP, miFetchOpcode },
|
||||||
|
/* 0x29 ORA imm */ { miFetchOperandLo, miFetchOpcode },
|
||||||
|
/* 0x2A ASL A */ { miFakeFetchOperand, miFetchOpcode },
|
||||||
|
/* 0x2B --- */ { miFetchOpcode },
|
||||||
|
/* 0x2C --- */ { miFetchOpcode },
|
||||||
|
/* 0x2D ORA abs */ { miFetchOperandLo, miFetchOperandHi, miReadAddress, miFetchOpcode },
|
||||||
|
/* 0x2E ASL abs */ { miFetchOperandLo, miFetchOperandHi, miReadAddress, miWriteAddress, miWriteAddress, miFetchOpcode },
|
||||||
|
/* 0x2F --- */ { miFetchOpcode },
|
||||||
|
|
||||||
|
/* 0x30 BPL */ { miFetchOperandAndCheckBranch, miCheckIfPageCrossed, miFakeFetchOperand, miFetchOpcode },
|
||||||
|
/* 0x31 ORA ind,Y */ { miFetchOperandLo, miFetchAddressLo, miFetchAddressHiAndIndex, miReadAddressAndSkip, miReadAddress, miFetchOpcode },
|
||||||
|
/* 0x32 --- */ { miFetchOpcode },
|
||||||
|
/* 0x33 --- */ { miFetchOpcode },
|
||||||
|
/* 0x34 --- */ { miFetchOpcode },
|
||||||
|
/* 0x35 ORA zpg,X */ { miFetchOperandLo, miIndexX, miReadAddress, miFetchOpcode },
|
||||||
|
/* 0x36 ASL zpg,X */ { miFetchOperandLo, miIndexX, miReadAddress, miWriteAddress, miWriteAddress, miFetchOpcode },
|
||||||
|
/* 0x37 --- */ { miFetchOpcode },
|
||||||
|
/* 0x38 CLC */ { miFetchOperandLo, miFetchOpcode },
|
||||||
|
/* 0x39 ORA abs,Y */ { miFetchOperandLo, miFetchOperandHiAndIndexY, miReadAddressAndSkip, miReadAddress, miFetchOpcode },
|
||||||
|
/* 0x3A --- */ { miFetchOpcode },
|
||||||
|
/* 0x3B --- */ { miFetchOpcode },
|
||||||
|
/* 0x3C --- */ { miFetchOpcode },
|
||||||
|
/* 0x3D ORA abs,X */ { miFetchOperandLo, miFetchOperandHiAndIndexX, miReadAddressAndSkip, miReadAddress, miFetchOpcode },
|
||||||
|
/* 0x3E ASL abs,X */ { miFetchOperandLo, miFetchOperandHiAndIndexX, miReadAddress, miReadAddress, miWriteAddress, miWriteAddress, miFetchOpcode },
|
||||||
|
/* 0x3F --- */ { miFetchOpcode },
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void SetFlags(uint8_t flags)
|
void SetFlags(uint8_t flags)
|
||||||
@@ -127,6 +182,19 @@ namespace m6502
|
|||||||
void DoOpcodeWork()
|
void DoOpcodeWork()
|
||||||
{
|
{
|
||||||
switch (rI&0x03) {
|
switch (rI&0x03) {
|
||||||
|
case 0: /* Clear/set flags*/
|
||||||
|
if ( (rI&0x1c)==0x18 ) {
|
||||||
|
switch (rI>>5) {
|
||||||
|
case 0: rP &= ~fC; break;
|
||||||
|
case 1: rP |= fC; break;
|
||||||
|
case 2: rP &= ~fI; break;
|
||||||
|
case 3: rP |= fI; break;
|
||||||
|
case 5: rP &= ~fV; break;
|
||||||
|
case 6: rP &= ~fD; break;
|
||||||
|
case 7: rP |= fD; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 1: /* ALU */
|
case 1: /* ALU */
|
||||||
switch ((rI>>5)&0x07) {
|
switch ((rI>>5)&0x07) {
|
||||||
case 0: /* ORA */ rB = rA | rB; SetFlags(fN|fZ); rA = rB; break;
|
case 0: /* ORA */ rB = rA | rB; SetFlags(fN|fZ); rA = rB; break;
|
||||||
@@ -141,6 +209,27 @@ namespace m6502
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DoRMW()
|
||||||
|
{
|
||||||
|
switch (rI&0x03) {
|
||||||
|
case 2: /* RMW */
|
||||||
|
if ((rI & 0xF)==0xA) rB = rA;
|
||||||
|
switch ((rI>>5)&0x07) {
|
||||||
|
case 0: /* ASL */ rP = ( rP & ~fC ) | ( (rB & 0x80)>>7 ); rB = rB << 1; SetFlags(fN|fZ); break;
|
||||||
|
};
|
||||||
|
if ((rI & 0xF)==0xA) rA = rB;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BranchCondition()
|
||||||
|
{
|
||||||
|
const uint8_t flags[4] = {fN, fV, fC, fZ};
|
||||||
|
const uint8_t flag = flags[rI>>6];
|
||||||
|
const bool condition = (rI>>5)&1;
|
||||||
|
return (rP & flag) == condition;
|
||||||
|
}
|
||||||
|
|
||||||
void InsertFetchOpcode()
|
void InsertFetchOpcode()
|
||||||
{
|
{
|
||||||
microcode[microcode_pos] = miFetchOpcode;
|
microcode[microcode_pos] = miFetchOpcode;
|
||||||
@@ -174,12 +263,17 @@ namespace m6502
|
|||||||
|
|
||||||
void ReadAddressAndSkip() { rB = mem::read(rAD); rAD_hi += rTEMP_hi; if (rTEMP_hi) InsertFetchOpcode(); }
|
void ReadAddressAndSkip() { rB = mem::read(rAD); rAD_hi += rTEMP_hi; if (rTEMP_hi) InsertFetchOpcode(); }
|
||||||
void WriteRegister() { mem::write(rAD, (rI&3)==1 ? rA : (rI&3)==2 ? rX : rY ); }
|
void WriteRegister() { mem::write(rAD, (rI&3)==1 ? rA : (rI&3)==2 ? rX : rY ); }
|
||||||
|
void WriteAddress() { mem::write(rAD, rB); DoRMW(); }
|
||||||
|
void PushA() { mem::write(0x0100+(rS++), rA); }
|
||||||
|
void FetchOperandAndCheckBranch() { FetchOperandLo(); if (!BranchCondition()) InsertFetchOpcode(); else { rT = rPC_hi; rPC = rPC + (int8_t)rB; } }
|
||||||
|
void CheckIfPageCrossed() { FakeFetchOperand(); if (rPC_hi == rT) InsertFetchOpcode(); }
|
||||||
|
|
||||||
void (*microinstructions[miNumMicroinstructions])(void) {
|
void (*microinstructions[miNumMicroinstructions])(void) {
|
||||||
FetchOpcode, FakeFetchOperand, FetchOperandLo, FetchOperandHi, FetchOperandHiAndIndexX, FetchOperandHiAndIndexY,
|
FetchOpcode, FakeFetchOperand, FetchOperandLo, FetchOperandHi, FetchOperandHiAndIndexX, FetchOperandHiAndIndexY,
|
||||||
PushPCHi, PushPCLo, PushP, PCLoInt, PCHiInt,
|
PushPCHi, PushPCLo, PushP, PCLoInt, PCHiInt,
|
||||||
IndexX, FetchAddressLo, FetchAddressHi, FetchAddressHiAndIndex, ReadAddress,
|
IndexX, FetchAddressLo, FetchAddressHi, FetchAddressHiAndIndex, ReadAddress,
|
||||||
ReadAddressAndSkip, WriteRegister };
|
ReadAddressAndSkip, WriteRegister, WriteAddress, PushA, FetchOperandAndCheckBranch,
|
||||||
|
CheckIfPageCrossed };
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -202,8 +202,8 @@ WriteAddress
|
|||||||
Mem::Write(Address, B);
|
Mem::Write(Address, B);
|
||||||
DoOpcodeWork();
|
DoOpcodeWork();
|
||||||
|
|
||||||
CheckIfTaken
|
FetchOperandAndCheckBranch
|
||||||
FakeFetchOperand();
|
Address.Lo = B = Mem::Read(PC++);
|
||||||
If (!condition)
|
If (!condition)
|
||||||
InsertFetchOpcode();
|
InsertFetchOpcode();
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user