mirror of
https://github.com/mnaberez/py65.git
synced 2025-08-08 13:25:01 +00:00
first steps to support 65Org16 cpu
This commit is contained in:
@@ -17,11 +17,17 @@ class MPU:
|
|||||||
ZERO = 2
|
ZERO = 2
|
||||||
CARRY = 1
|
CARRY = 1
|
||||||
|
|
||||||
def __init__(self, memory=None, pc=0x0000, debug=False):
|
def __init__(self, memory=None, pc=0x0000, debug=False, byteWidth=8, addrWidth=16):
|
||||||
# config
|
# config
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
self.name = '6502'
|
self.name = '6502'
|
||||||
|
self.byteWidth = byteWidth
|
||||||
|
self.byteMask = ((1<<byteWidth)-1)
|
||||||
|
self.addrWidth = addrWidth
|
||||||
|
self.addrMask = ((1<<addrWidth)-1)
|
||||||
|
self.addrHighMask = (self.byteMask<<byteWidth)
|
||||||
|
self.spBase = 1<<byteWidth
|
||||||
|
|
||||||
# vm status
|
# vm status
|
||||||
self.excycles = 0
|
self.excycles = 0
|
||||||
self.addcycles = False
|
self.addcycles = False
|
||||||
@@ -35,30 +41,32 @@ class MPU:
|
|||||||
# init
|
# init
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
|
def reprformat(self):
|
||||||
|
return ("%s PC AC XR YR SP NV-BDIZC\n" + \
|
||||||
|
"%s: %04x %02x %02x %02x %02x %s"
|
||||||
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
flags = itoa(self.p, 2).rjust(8, '0')
|
flags = itoa(self.p, 2).rjust(self.byteWidth, '0')
|
||||||
indent = ' ' * (len(self.name) + 2)
|
indent = ' ' * (len(self.name) + 2)
|
||||||
|
|
||||||
out = "%s PC AC XR YR SP NV-BDIZC\n" + \
|
return self.reprformat() % (indent, self.name,
|
||||||
"%s: %04x %02x %02x %02x %02x %s"
|
|
||||||
|
|
||||||
return out % (indent, self.name,
|
|
||||||
self.pc, self.a, self.x, self.y, self.sp, flags)
|
self.pc, self.a, self.x, self.y, self.sp, flags)
|
||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
instructCode = self.ImmediateByte()
|
instructCode = self.ImmediateByte()
|
||||||
self.pc +=1
|
self.pc +=1
|
||||||
self.pc &=0xffff
|
self.pc &=self.addrMask
|
||||||
self.excycles = 0
|
self.excycles = 0
|
||||||
self.addcycles = self.extracycles[instructCode]
|
self.addcycles = self.extracycles[instructCode]
|
||||||
self.instruct[instructCode](self)
|
self.instruct[instructCode](self)
|
||||||
self.processorCycles += self.cycletime[instructCode]+self.excycles
|
self.processorCycles += self.cycletime[instructCode]+self.excycles
|
||||||
self.pc &= 0xffff
|
self.pc &= self.addrMask
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
self.pc = self.start_pc
|
self.pc = self.start_pc
|
||||||
self.sp = 255
|
self.sp = self.byteMask
|
||||||
self.a = 0
|
self.a = 0
|
||||||
self.x = 0
|
self.x = 0
|
||||||
self.y = 0
|
self.y = 0
|
||||||
@@ -71,11 +79,11 @@ class MPU:
|
|||||||
return self.memory[addr]
|
return self.memory[addr]
|
||||||
|
|
||||||
def WordAt(self, addr):
|
def WordAt(self, addr):
|
||||||
return self.ByteAt(addr) + (self.ByteAt(addr + 1) << 8)
|
return self.ByteAt(addr) + (self.ByteAt(addr + 1) << self.byteWidth)
|
||||||
|
|
||||||
def WrapAt(self, addr):
|
def WrapAt(self, addr):
|
||||||
wrap = lambda x: (x & 0xff00) + ((x + 1) & 0xff)
|
wrap = lambda x: (x & self.addrHighMask) + ((x + 1) & self.byteMask)
|
||||||
return self.ByteAt(addr) + (self.ByteAt(wrap(addr)) << 8)
|
return self.ByteAt(addr) + (self.ByteAt(wrap(addr)) << self.byteWidth)
|
||||||
|
|
||||||
def ProgramCounter(self):
|
def ProgramCounter(self):
|
||||||
return self.pc
|
return self.pc
|
||||||
@@ -89,23 +97,23 @@ class MPU:
|
|||||||
return self.ByteAt(self.pc)
|
return self.ByteAt(self.pc)
|
||||||
|
|
||||||
def ZeroPageXAddr(self):
|
def ZeroPageXAddr(self):
|
||||||
return 255 & (self.x + self.ByteAt(self.pc))
|
return self.byteMask & (self.x + self.ByteAt(self.pc))
|
||||||
|
|
||||||
def ZeroPageYAddr(self):
|
def ZeroPageYAddr(self):
|
||||||
return 255 & (self.y + self.ByteAt(self.pc))
|
return self.byteMask & (self.y + self.ByteAt(self.pc))
|
||||||
|
|
||||||
def IndirectXAddr(self):
|
def IndirectXAddr(self):
|
||||||
return self.WrapAt( 255 & (self.ByteAt(self.pc) + self.x))
|
return self.WrapAt( self.byteMask & (self.ByteAt(self.pc) + self.x))
|
||||||
|
|
||||||
def IndirectYAddr(self):
|
def IndirectYAddr(self):
|
||||||
if self.addcycles:
|
if self.addcycles:
|
||||||
a1 = self.WrapAt(self.ByteAt(self.pc))
|
a1 = self.WrapAt(self.ByteAt(self.pc))
|
||||||
a2 = (a1+self.y) & 0xffff
|
a2 = (a1+self.y) & self.addrMask
|
||||||
if (a1 & 0xff00) != (a2 & 0xff00):
|
if (a1 & self.addrHighMask) != (a2 & self.addrHighMask):
|
||||||
self.excycles += 1
|
self.excycles += 1
|
||||||
return a2
|
return a2
|
||||||
else:
|
else:
|
||||||
return (self.WrapAt(self.ByteAt(self.pc))+self.y)&0xffff
|
return (self.WrapAt(self.ByteAt(self.pc))+self.y)&self.addrMask
|
||||||
|
|
||||||
def AbsoluteAddr(self):
|
def AbsoluteAddr(self):
|
||||||
return self.WordAt(self.pc)
|
return self.WordAt(self.pc)
|
||||||
@@ -113,57 +121,57 @@ class MPU:
|
|||||||
def AbsoluteXAddr(self):
|
def AbsoluteXAddr(self):
|
||||||
if self.addcycles:
|
if self.addcycles:
|
||||||
a1 = self.WordAt(self.pc)
|
a1 = self.WordAt(self.pc)
|
||||||
a2 = (a1 + self.x) & 0xffff
|
a2 = (a1 + self.x) & self.addrMask
|
||||||
if (a1 & 0xff00) != (a2 & 0xff00):
|
if (a1 & self.addrHighMask) != (a2 & self.addrHighMask):
|
||||||
self.excycles += 1
|
self.excycles += 1
|
||||||
return a2
|
return a2
|
||||||
else:
|
else:
|
||||||
return (self.WordAt(self.pc)+self.x)&0xffff
|
return (self.WordAt(self.pc)+self.x)&self.addrMask
|
||||||
|
|
||||||
def AbsoluteYAddr(self):
|
def AbsoluteYAddr(self):
|
||||||
if self.addcycles:
|
if self.addcycles:
|
||||||
a1 = self.WordAt(self.pc)
|
a1 = self.WordAt(self.pc)
|
||||||
a2 = (a1 + self.y) & 0xffff
|
a2 = (a1 + self.y) & self.addrMask
|
||||||
if (a1 & 0xff00) != (a2 & 0xff00):
|
if (a1 & self.addrHighMask) != (a2 & self.addrHighMask):
|
||||||
self.excycles += 1
|
self.excycles += 1
|
||||||
return a2
|
return a2
|
||||||
else:
|
else:
|
||||||
return (self.WordAt(self.pc)+self.y)&0xffff
|
return (self.WordAt(self.pc)+self.y)&self.addrMask
|
||||||
|
|
||||||
def BranchRelAddr(self):
|
def BranchRelAddr(self):
|
||||||
self.excycles += 1
|
self.excycles += 1
|
||||||
addr = self.ImmediateByte()
|
addr = self.ImmediateByte()
|
||||||
self.pc += 1
|
self.pc += 1
|
||||||
|
|
||||||
if addr & 128:
|
if addr & self.NEGATIVE:
|
||||||
addr = self.pc - (addr ^ 0xFF) - 1
|
addr = self.pc - (addr ^ self.byteMask) - 1
|
||||||
else:
|
else:
|
||||||
addr = self.pc + addr
|
addr = self.pc + addr
|
||||||
|
|
||||||
if (self.pc & 0xff00) != (addr & 0xff00):
|
if (self.pc & self.addrHighMask) != (addr & self.addrHighMask):
|
||||||
self.excycles += 1
|
self.excycles += 1
|
||||||
|
|
||||||
self.pc = addr & 0xffff
|
self.pc = addr & self.addrMask
|
||||||
|
|
||||||
# stack
|
# stack
|
||||||
|
|
||||||
def stPush(self,z):
|
def stPush(self,z):
|
||||||
self.memory[self.sp+256] = z&255
|
self.memory[self.sp+self.spBase] = z&self.byteMask
|
||||||
self.sp -= 1
|
self.sp -= 1
|
||||||
self.sp &= 255
|
self.sp &= self.byteMask
|
||||||
|
|
||||||
def stPop(self):
|
def stPop(self):
|
||||||
self.sp += 1
|
self.sp += 1
|
||||||
self.sp &= 255
|
self.sp &= self.byteMask
|
||||||
return self.ByteAt(self.sp+256)
|
return self.ByteAt(self.sp+self.spBase)
|
||||||
|
|
||||||
def stPushWord(self, z):
|
def stPushWord(self, z):
|
||||||
self.stPush((z>>8)&255)
|
self.stPush((z>>self.byteWidth)&self.byteMask)
|
||||||
self.stPush(z&255)
|
self.stPush(z&self.byteMask)
|
||||||
|
|
||||||
def stPopWord(self):
|
def stPopWord(self):
|
||||||
z = self.stPop()
|
z = self.stPop()
|
||||||
z += 256*self.stPop()
|
z += self.stPop()<<self.byteWidth
|
||||||
return z
|
return z
|
||||||
|
|
||||||
def FlagsNZ(self, value):
|
def FlagsNZ(self, value):
|
||||||
@@ -188,12 +196,12 @@ class MPU:
|
|||||||
|
|
||||||
self.p &= ~(self.CARRY + self.NEGATIVE + self.ZERO)
|
self.p &= ~(self.CARRY + self.NEGATIVE + self.ZERO)
|
||||||
|
|
||||||
if tbyte & 128:
|
if tbyte & self.NEGATIVE:
|
||||||
self.p |= self.CARRY
|
self.p |= self.CARRY
|
||||||
tbyte = (tbyte << 1) & 0xFF
|
tbyte = (tbyte << 1) & self.byteMask
|
||||||
|
|
||||||
if tbyte:
|
if tbyte:
|
||||||
self.p |= tbyte & 128
|
self.p |= tbyte & self.NEGATIVE
|
||||||
else:
|
else:
|
||||||
self.p |= self.ZERO
|
self.p |= self.ZERO
|
||||||
|
|
||||||
@@ -250,7 +258,7 @@ class MPU:
|
|||||||
self.p &=~(self.ZERO+self.NEGATIVE+self.OVERFLOW)
|
self.p &=~(self.ZERO+self.NEGATIVE+self.OVERFLOW)
|
||||||
if (self.a & tbyte) == 0:
|
if (self.a & tbyte) == 0:
|
||||||
self.p |= self.ZERO
|
self.p |= self.ZERO
|
||||||
self.p |= tbyte&(128+64)
|
self.p |= tbyte&(self.NEGATIVE+self.OVERFLOW)
|
||||||
|
|
||||||
def opROL(self, x):
|
def opROL(self, x):
|
||||||
if x is None:
|
if x is None:
|
||||||
@@ -260,16 +268,16 @@ class MPU:
|
|||||||
tbyte = self.ByteAt(addr)
|
tbyte = self.ByteAt(addr)
|
||||||
|
|
||||||
if self.p & self.CARRY:
|
if self.p & self.CARRY:
|
||||||
if tbyte & 128:
|
if tbyte & self.NEGATIVE:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
self.p &= ~self.CARRY
|
self.p &= ~self.CARRY
|
||||||
tbyte = (tbyte << 1) | 1
|
tbyte = (tbyte << 1) | 1
|
||||||
else:
|
else:
|
||||||
if tbyte & 128:
|
if tbyte & self.NEGATIVE:
|
||||||
self.p |= self.CARRY
|
self.p |= self.CARRY
|
||||||
tbyte = tbyte << 1
|
tbyte = tbyte << 1
|
||||||
tbyte &= 0xFF
|
tbyte &= self.byteMask
|
||||||
self.FlagsNZ(tbyte)
|
self.FlagsNZ(tbyte)
|
||||||
|
|
||||||
if x is None:
|
if x is None:
|
||||||
@@ -313,7 +321,7 @@ class MPU:
|
|||||||
self.p |= aluresult & self.NEGATIVE
|
self.p |= aluresult & self.NEGATIVE
|
||||||
if decimalcarry == 1:
|
if decimalcarry == 1:
|
||||||
self.p |= self.CARRY
|
self.p |= self.CARRY
|
||||||
if ( ~(self.a ^ data) & (self.a ^ aluresult) ) & 0x80:
|
if ( ~(self.a ^ data) & (self.a ^ aluresult) ) & self.NEGATIVE:
|
||||||
self.p |= self.OVERFLOW
|
self.p |= self.OVERFLOW
|
||||||
self.a = (nibble1 << 4) + nibble0
|
self.a = (nibble1 << 4) + nibble0
|
||||||
else:
|
else:
|
||||||
@@ -323,12 +331,12 @@ class MPU:
|
|||||||
tmp = 0
|
tmp = 0
|
||||||
result = data + self.a + tmp
|
result = data + self.a + tmp
|
||||||
self.p &= ~(self.CARRY+self.OVERFLOW+self.NEGATIVE+self.ZERO)
|
self.p &= ~(self.CARRY+self.OVERFLOW+self.NEGATIVE+self.ZERO)
|
||||||
if ( ~(self.a ^ data) & (self.a ^ result) ) & 0x80:
|
if ( ~(self.a ^ data) & (self.a ^ result) ) & self.NEGATIVE:
|
||||||
self.p |= self.OVERFLOW
|
self.p |= self.OVERFLOW
|
||||||
data = result
|
data = result
|
||||||
if data > 255:
|
if data > self.byteMask:
|
||||||
self.p |= self.CARRY
|
self.p |= self.CARRY
|
||||||
data &=255
|
data &=self.byteMask
|
||||||
if data == 0:
|
if data == 0:
|
||||||
self.p |= self.ZERO
|
self.p |= self.ZERO
|
||||||
else:
|
else:
|
||||||
@@ -347,7 +355,7 @@ class MPU:
|
|||||||
pass # {}
|
pass # {}
|
||||||
else:
|
else:
|
||||||
self.p &=~ self.CARRY
|
self.p &=~ self.CARRY
|
||||||
tbyte=(tbyte>>1)|128
|
tbyte=(tbyte>>1)|self.NEGATIVE
|
||||||
else:
|
else:
|
||||||
if tbyte & 1:
|
if tbyte & 1:
|
||||||
self.p |= self.CARRY
|
self.p |= self.CARRY
|
||||||
@@ -395,10 +403,10 @@ class MPU:
|
|||||||
adjust1 = 10 << 4
|
adjust1 = 10 << 4
|
||||||
|
|
||||||
# the ALU outputs are not decimally adjusted
|
# the ALU outputs are not decimally adjusted
|
||||||
aluresult = self.a + (~data & 0xFF) + (self.p & self.CARRY)
|
aluresult = self.a + (~data & self.byteMask) + (self.p & self.CARRY)
|
||||||
if aluresult > 0xff:
|
if aluresult > self.byteMask:
|
||||||
decimalcarry = 1
|
decimalcarry = 1
|
||||||
aluresult &= 0xff
|
aluresult &= self.byteMask
|
||||||
|
|
||||||
# but the final result will be adjusted
|
# but the final result will be adjusted
|
||||||
nibble0 = (aluresult + adjust0) & 0xf
|
nibble0 = (aluresult + adjust0) & 0xf
|
||||||
@@ -411,7 +419,7 @@ class MPU:
|
|||||||
self.p |= aluresult & self.NEGATIVE
|
self.p |= aluresult & self.NEGATIVE
|
||||||
if decimalcarry == 1:
|
if decimalcarry == 1:
|
||||||
self.p |= self.CARRY
|
self.p |= self.CARRY
|
||||||
if ( (self.a ^ data) & (self.a ^ aluresult) ) & 0x80:
|
if ( (self.a ^ data) & (self.a ^ aluresult) ) & self.NEGATIVE:
|
||||||
self.p |= self.OVERFLOW
|
self.p |= self.OVERFLOW
|
||||||
self.a = (nibble1 << 4) + nibble0
|
self.a = (nibble1 << 4) + nibble0
|
||||||
else:
|
else:
|
||||||
@@ -420,11 +428,11 @@ class MPU:
|
|||||||
else:
|
else:
|
||||||
borrow = 1
|
borrow = 1
|
||||||
|
|
||||||
result = self.a + (~data & 0xFF) + (self.p & self.CARRY)
|
result = self.a + (~data & self.byteMask) + (self.p & self.CARRY)
|
||||||
self.p &= ~(self.CARRY + self.ZERO + self.OVERFLOW + self.NEGATIVE)
|
self.p &= ~(self.CARRY + self.ZERO + self.OVERFLOW + self.NEGATIVE)
|
||||||
if ( (self.a ^ data) & (self.a ^ result) ) & 0x80:
|
if ( (self.a ^ data) & (self.a ^ result) ) & self.NEGATIVE:
|
||||||
self.p |= self.OVERFLOW
|
self.p |= self.OVERFLOW
|
||||||
data = result & 0xFF
|
data = result & self.byteMask
|
||||||
if data == 0:
|
if data == 0:
|
||||||
self.p |= self.ZERO
|
self.p |= self.ZERO
|
||||||
if result & 0x100:
|
if result & 0x100:
|
||||||
@@ -440,7 +448,7 @@ class MPU:
|
|||||||
tbyte = self.ByteAt(addr)
|
tbyte = self.ByteAt(addr)
|
||||||
|
|
||||||
self.p &= ~(self.ZERO + self.NEGATIVE)
|
self.p &= ~(self.ZERO + self.NEGATIVE)
|
||||||
tbyte = (tbyte - 1) & 0xFF
|
tbyte = (tbyte - 1) & self.byteMask
|
||||||
if tbyte:
|
if tbyte:
|
||||||
self.p |= tbyte & self.NEGATIVE
|
self.p |= tbyte & self.NEGATIVE
|
||||||
else:
|
else:
|
||||||
@@ -459,7 +467,7 @@ class MPU:
|
|||||||
tbyte = self.ByteAt(addr)
|
tbyte = self.ByteAt(addr)
|
||||||
|
|
||||||
self.p &= ~(self.ZERO + self.NEGATIVE)
|
self.p &= ~(self.ZERO + self.NEGATIVE)
|
||||||
tbyte = (tbyte + 1) & 0xFF
|
tbyte = (tbyte + 1) & self.byteMask
|
||||||
if tbyte:
|
if tbyte:
|
||||||
self.p |= tbyte & self.NEGATIVE
|
self.p |= tbyte & self.NEGATIVE
|
||||||
else:
|
else:
|
||||||
@@ -499,7 +507,7 @@ class MPU:
|
|||||||
|
|
||||||
@instruction(name="BRK", mode="imp", cycles=7)
|
@instruction(name="BRK", mode="imp", cycles=7)
|
||||||
def inst_0x00(self):
|
def inst_0x00(self):
|
||||||
pc = (self.pc + 1) & 0xFFFF # The pc has already been increased one
|
pc = (self.pc + 1) & self.addrMask # The pc has already been increased one
|
||||||
self.stPushWord(pc)
|
self.stPushWord(pc)
|
||||||
|
|
||||||
self.p |= self.BREAK
|
self.p |= self.BREAK
|
||||||
@@ -586,7 +594,7 @@ class MPU:
|
|||||||
|
|
||||||
@instruction(name="JSR", mode="abs", cycles=6)
|
@instruction(name="JSR", mode="abs", cycles=6)
|
||||||
def inst_0x20(self):
|
def inst_0x20(self):
|
||||||
self.stPushWord((self.pc+1)&0xffff)
|
self.stPushWord((self.pc+1)&self.addrMask)
|
||||||
self.pc=self.WordAt(self.pc)
|
self.pc=self.WordAt(self.pc)
|
||||||
|
|
||||||
@instruction(name="AND", mode="inx", cycles=6)
|
@instruction(name="AND", mode="inx", cycles=6)
|
||||||
@@ -870,7 +878,7 @@ class MPU:
|
|||||||
@instruction(name="DEY", mode="imp", cycles=2)
|
@instruction(name="DEY", mode="imp", cycles=2)
|
||||||
def inst_0x88(self):
|
def inst_0x88(self):
|
||||||
self.y -= 1
|
self.y -= 1
|
||||||
self.y&=255
|
self.y&=self.byteMask
|
||||||
self.FlagsNZ(self.y)
|
self.FlagsNZ(self.y)
|
||||||
|
|
||||||
@instruction(name="TXA", mode="imp", cycles=2)
|
@instruction(name="TXA", mode="imp", cycles=2)
|
||||||
@@ -1077,7 +1085,7 @@ class MPU:
|
|||||||
@instruction(name="INY", mode="imp", cycles=2)
|
@instruction(name="INY", mode="imp", cycles=2)
|
||||||
def inst_0xc8(self):
|
def inst_0xc8(self):
|
||||||
self.y += 1
|
self.y += 1
|
||||||
self.y &= 255
|
self.y &= self.byteMask
|
||||||
self.FlagsNZ(self.y)
|
self.FlagsNZ(self.y)
|
||||||
|
|
||||||
@instruction(name="CMP", mode="imm", cycles=2)
|
@instruction(name="CMP", mode="imm", cycles=2)
|
||||||
@@ -1088,7 +1096,7 @@ class MPU:
|
|||||||
@instruction(name="DEX", mode="imp", cycles=2)
|
@instruction(name="DEX", mode="imp", cycles=2)
|
||||||
def inst_0xca(self):
|
def inst_0xca(self):
|
||||||
self.x -= 1
|
self.x -= 1
|
||||||
self.x &= 255
|
self.x &= self.byteMask
|
||||||
self.FlagsNZ(self.x)
|
self.FlagsNZ(self.x)
|
||||||
|
|
||||||
@instruction(name="CPY", mode="abs", cycles=4)
|
@instruction(name="CPY", mode="abs", cycles=4)
|
||||||
@@ -1172,7 +1180,7 @@ class MPU:
|
|||||||
@instruction(name="INX", mode="imp", cycles=2)
|
@instruction(name="INX", mode="imp", cycles=2)
|
||||||
def inst_0xe8(self):
|
def inst_0xe8(self):
|
||||||
self.x+=1
|
self.x+=1
|
||||||
self.x&=255
|
self.x&=self.byteMask
|
||||||
self.FlagsNZ(self.x)
|
self.FlagsNZ(self.x)
|
||||||
|
|
||||||
@instruction(name="SBC", mode="imm", cycles=2)
|
@instruction(name="SBC", mode="imm", cycles=2)
|
||||||
@@ -1236,4 +1244,3 @@ class MPU:
|
|||||||
def inst_0xfe(self):
|
def inst_0xfe(self):
|
||||||
self.opINCR(self.AbsoluteXAddr)
|
self.opINCR(self.AbsoluteXAddr)
|
||||||
self.pc += 2
|
self.pc += 2
|
||||||
|
|
||||||
|
32
src/py65/devices/mpu65Org16.py
Normal file
32
src/py65/devices/mpu65Org16.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
from py65.devices import mpu6502
|
||||||
|
from py65.utils.devices import make_instruction_decorator
|
||||||
|
|
||||||
|
class MPU(mpu6502.MPU):
|
||||||
|
|
||||||
|
def __init__(self, byteWidth=16, addrWidth=32, *args, **kwargs):
|
||||||
|
mpu6502.MPU.__init__(self, byteWidth=byteWidth, addrWidth=addrWidth, *args, **kwargs)
|
||||||
|
self.name = '65Org16'
|
||||||
|
self.waiting = False
|
||||||
|
self.IrqTo = (1<<self.addrWidth)-2
|
||||||
|
self.ResetTo = (1<<self.addrWidth)-4
|
||||||
|
self.NMITo = (1<<self.addrWidth)-6
|
||||||
|
self.NEGATIVE = 1 << 15
|
||||||
|
self.OVERFLOW = 1 << 14
|
||||||
|
|
||||||
|
def step(self):
|
||||||
|
if self.waiting:
|
||||||
|
self.processorCycles += 1
|
||||||
|
else:
|
||||||
|
mpu6502.MPU.step(self)
|
||||||
|
return self
|
||||||
|
|
||||||
|
# Make copies of the lists
|
||||||
|
instruct = mpu6502.MPU.instruct[:]
|
||||||
|
cycletime = mpu6502.MPU.cycletime[:]
|
||||||
|
extracycles = mpu6502.MPU.extracycles[:]
|
||||||
|
disassemble = mpu6502.MPU.disassemble[:]
|
||||||
|
|
||||||
|
def reprformat(self):
|
||||||
|
return ("%s PC AC XR YR SP NV---------BDIZC\n" + \
|
||||||
|
"%s: %08x %04x %04x %04x %04x %s"
|
||||||
|
)
|
@@ -1,8 +1,21 @@
|
|||||||
|
# this sparse array module only needed for large-memory CPU models
|
||||||
|
try:
|
||||||
|
from blist import *
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
class ObservableMemory:
|
class ObservableMemory:
|
||||||
def __init__(self, subject=None):
|
def __init__(self, subject=None, addrWidth=16):
|
||||||
if subject is None:
|
if subject is None:
|
||||||
subject = 0x10000 * [0x00]
|
if addrWidth <= 16:
|
||||||
|
subject = 0x10000 * [0x00]
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
subject = blist([0]) * (1 << addrWidth)
|
||||||
|
except:
|
||||||
|
print "Fatal: failed to initialise large memory for this CPU"
|
||||||
|
exit (1)
|
||||||
|
|
||||||
self._subject = subject
|
self._subject = subject
|
||||||
|
|
||||||
self._read_subscribers = {}
|
self._read_subscribers = {}
|
||||||
|
@@ -8,6 +8,7 @@ import sys
|
|||||||
from asyncore import compact_traceback
|
from asyncore import compact_traceback
|
||||||
from py65.devices.mpu6502 import MPU as NMOS6502
|
from py65.devices.mpu6502 import MPU as NMOS6502
|
||||||
from py65.devices.mpu65c02 import MPU as CMOS65C02
|
from py65.devices.mpu65c02 import MPU as CMOS65C02
|
||||||
|
from py65.devices.mpu65Org16 import MPU as V65Org16
|
||||||
from py65.disassembler import Disassembler
|
from py65.disassembler import Disassembler
|
||||||
from py65.assembler import Assembler
|
from py65.assembler import Assembler
|
||||||
from py65.utils.addressing import AddressParser
|
from py65.utils.addressing import AddressParser
|
||||||
@@ -112,7 +113,7 @@ class Monitor(cmd.Cmd):
|
|||||||
byte = 0
|
byte = 0
|
||||||
return byte
|
return byte
|
||||||
|
|
||||||
m = ObservableMemory()
|
m = ObservableMemory(addrWidth=self._mpu.addrWidth)
|
||||||
m.subscribe_to_write([0xF001], putc)
|
m.subscribe_to_write([0xF001], putc)
|
||||||
m.subscribe_to_read([0xF004], getc)
|
m.subscribe_to_read([0xF004], getc)
|
||||||
|
|
||||||
@@ -147,7 +148,7 @@ class Monitor(cmd.Cmd):
|
|||||||
self._reset(mpu_type=klass)
|
self._reset(mpu_type=klass)
|
||||||
|
|
||||||
def do_mpu(self, args):
|
def do_mpu(self, args):
|
||||||
mpus = {'6502': NMOS6502, '65C02': CMOS65C02}
|
mpus = {'6502': NMOS6502, '65C02': CMOS65C02, '65Org16': V65Org16}
|
||||||
|
|
||||||
def available_mpus():
|
def available_mpus():
|
||||||
mpu_list = ', '.join(mpus.keys())
|
mpu_list = ', '.join(mpus.keys())
|
||||||
@@ -157,7 +158,7 @@ class Monitor(cmd.Cmd):
|
|||||||
self._output("Current MPU is %s" % self._mpu.name)
|
self._output("Current MPU is %s" % self._mpu.name)
|
||||||
available_mpus()
|
available_mpus()
|
||||||
else:
|
else:
|
||||||
requested = args.upper()
|
requested = args
|
||||||
new_mpu = mpus.get(requested, None)
|
new_mpu = mpus.get(requested, None)
|
||||||
if new_mpu is None:
|
if new_mpu is None:
|
||||||
self._output("Unknown MPU: %s" % args)
|
self._output("Unknown MPU: %s" % args)
|
||||||
|
Reference in New Issue
Block a user