mirror of
https://github.com/rzzzwilson/pymlac.git
synced 2025-06-10 09:32:41 +00:00
Getting Imlac machine running, test loading
This commit is contained in:
@@ -169,7 +169,7 @@ class MainCPU(object):
|
||||
return self.BlockBase | address
|
||||
|
||||
def execute_one_instruction(self):
|
||||
"""Execute one MAIN instruction, return # cycles used"""
|
||||
"""Execute one MAIN instruction, return # cycles used and if traced."""
|
||||
|
||||
if not self.running:
|
||||
return 0
|
||||
@@ -187,6 +187,7 @@ class MainCPU(object):
|
||||
return self.main_decode.get(opcode, self.illegal)(indirect,
|
||||
address,
|
||||
instruction)
|
||||
|
||||
def illegal(self, indirect, address, instruction):
|
||||
"""Handle an illegal instruction."""
|
||||
|
||||
@@ -208,33 +209,34 @@ class MainCPU(object):
|
||||
instruction)
|
||||
|
||||
def i_LAW_LWC(self, indirect, address, instruction):
|
||||
traced = False
|
||||
if indirect:
|
||||
self.AC = ~address & WORDMASK
|
||||
trace.itrace('LWC', False, address)
|
||||
traced = trace.itrace('LWC', False, address)
|
||||
else:
|
||||
self.AC = address
|
||||
trace.itrace('LAW', False, address)
|
||||
return 1
|
||||
traced = trace.itrace('LAW', False, address)
|
||||
return (1, traced)
|
||||
|
||||
def i_JMP(self, indirect, address, instruction):
|
||||
address = self.memory.eff_address(address, indirect)
|
||||
self.PC = address & PCMASK
|
||||
trace.itrace('JMP', indirect, address)
|
||||
return 3 if indirect else 2
|
||||
traced = trace.itrace('JMP', indirect, address)
|
||||
return (3, traced) if indirect else (2, traced)
|
||||
|
||||
def i_DAC(self, indirect, address, instruction):
|
||||
address = self.memory.eff_address(address, indirect)
|
||||
self.memory.put(self.AC, address, False)
|
||||
trace.itrace('DAC', indirect, address)
|
||||
return 3 if indirect else 2
|
||||
traced = trace.itrace('DAC', indirect, address)
|
||||
return (3, traced) if indirect else (2, traced)
|
||||
|
||||
def i_XAM(self, indirect, address, instruction):
|
||||
address = self.memory.eff_address(address, indirect)
|
||||
tmp = self.memory.fetch(address, False)
|
||||
self.memory.put(self.AC, address, False)
|
||||
self.AC = tmp
|
||||
trace.itrace('XAM', indirect, address)
|
||||
return 3 if indirect else 2
|
||||
traced = trace.itrace('XAM', indirect, address)
|
||||
return (3, traced) if indirect else (2, traced)
|
||||
|
||||
def i_ISZ(self, indirect, address, instruction):
|
||||
address = self.memory.eff_address(address, indirect)
|
||||
@@ -242,43 +244,43 @@ class MainCPU(object):
|
||||
self.memory.put(value, address, False)
|
||||
if value == 0:
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('ISZ', indirect, address)
|
||||
return 3 if indirect else 2
|
||||
traced = trace.itrace('ISZ', indirect, address)
|
||||
return (3, traced) if indirect else (2, traced)
|
||||
|
||||
def i_JMS(self, indirect, address, instruction):
|
||||
address = self.memory.eff_address(address, indirect)
|
||||
self.memory.put(self.PC, address, False)
|
||||
self.PC = (address + 1) & PCMASK
|
||||
trace.itrace('JMS', indirect, address)
|
||||
return 3 if indirect else 2
|
||||
traced = trace.itrace('JMS', indirect, address)
|
||||
return (3, traced) if indirect else (2, traced)
|
||||
|
||||
def i_AND(self, indirect, address, instruction):
|
||||
self.AC &= self.memory.fetch(address, indirect)
|
||||
trace.itrace('AND', indirect, address)
|
||||
return 3 if indirect else 2
|
||||
traced = trace.itrace('AND', indirect, address)
|
||||
return (3, traced) if indirect else (2, traced)
|
||||
|
||||
def i_IOR(self, indirect, address, instruction):
|
||||
self.AC |= self.memory.fetch(address, indirect)
|
||||
trace.itrace('IOR', indirect, address)
|
||||
return 3 if indirect else 2
|
||||
traced = trace.itrace('IOR', indirect, address)
|
||||
return (3, traced) if indirect else (2, traced)
|
||||
|
||||
def i_XOR(self, indirect, address, instruction):
|
||||
self.AC ^= self.memory.fetch(address, indirect)
|
||||
trace.itrace('XOR', indirect, address)
|
||||
return 3 if indirect else 2
|
||||
traced = trace.itrace('XOR', indirect, address)
|
||||
return (3, traced) if indirect else (2, traced)
|
||||
|
||||
def i_LAC(self, indirect, address, instruction):
|
||||
self.AC = self.memory.fetch(address, indirect)
|
||||
trace.itrace('LAC', indirect, address)
|
||||
return 3 if indirect else 2
|
||||
traced = trace.itrace('LAC', indirect, address)
|
||||
return (3, traced) if indirect else (2, traced)
|
||||
|
||||
def i_ADD(self, indirect, address, instruction):
|
||||
self.AC += self.memory.fetch(self.BLOCKADDR(address), indirect)
|
||||
if self.AC & OVERFLOWMASK:
|
||||
self.L = (~self.L) & 01
|
||||
self.AC &= WORDMASK
|
||||
trace.itrace('ADD', indirect, address)
|
||||
return 3 if indirect else 2
|
||||
traced = trace.itrace('ADD', indirect, address)
|
||||
return (3, traced) if indirect else (2, traced)
|
||||
|
||||
def i_SUB(self, indirect, address, instruction):
|
||||
addit = self.memory.fetch(self.BLOCKADDR(address), indirect)
|
||||
@@ -287,15 +289,15 @@ class MainCPU(object):
|
||||
if self.AC & OVERFLOWMASK:
|
||||
self.L = ~self.L
|
||||
self.AC &= WORDMASK
|
||||
trace.itrace('SUB', indirect, address)
|
||||
return 3 if indirect else 2
|
||||
traced = trace.itrace('SUB', indirect, address)
|
||||
return (3, traced) if indirect else (2, traced)
|
||||
|
||||
def i_SAM(self, indirect, address, instruction):
|
||||
samaddr = self.BLOCKADDR(address)
|
||||
if self.AC == self.memory.fetch(samaddr, indirect):
|
||||
self.PC = (self.PC + 1) & PCMASK
|
||||
trace.itrace('SAM', indirect, address)
|
||||
return 3 if indirect else 2
|
||||
traced = trace.itrace('SAM', indirect, address)
|
||||
return (3, traced) if indirect else (2, traced)
|
||||
|
||||
def microcode(self, instruction):
|
||||
# T1
|
||||
@@ -336,149 +338,149 @@ class MainCPU(object):
|
||||
if instruction & k:
|
||||
combine.append(op)
|
||||
|
||||
trace.itrace('+'.join(combine), False)
|
||||
return 1
|
||||
traced = trace.itrace('+'.join(combine), False)
|
||||
return (1, traced)
|
||||
|
||||
def i_DLA(self, indirect, address, instruction):
|
||||
self.displaycpu.DPC = self.AC
|
||||
trace.itrace('DLA')
|
||||
return 1
|
||||
traced = trace.itrace('DLA')
|
||||
return (1, traced)
|
||||
|
||||
def i_CTB(self, indirect, address, instruction):
|
||||
trace.itrace('CTB')
|
||||
return 1
|
||||
traced = trace.itrace('CTB')
|
||||
return (1, traced)
|
||||
|
||||
def i_DOF(self, indirect, address, instruction):
|
||||
self.displaycpu.stop()
|
||||
trace.itrace('DOF')
|
||||
return 1
|
||||
traced = trace.itrace('DOF')
|
||||
return (1, traced)
|
||||
|
||||
def i_KRB(self, indirect, address, instruction):
|
||||
self.AC |= self.kbd.read()
|
||||
trace.itrace('KRB')
|
||||
return 1
|
||||
traced = trace.itrace('KRB')
|
||||
return (1, traced)
|
||||
|
||||
def i_KCF(self, indirect, address, instruction):
|
||||
self.kbd.clear()
|
||||
trace.itrace('KCF')
|
||||
return 1
|
||||
traced = trace.itrace('KCF')
|
||||
return (1, traced)
|
||||
|
||||
def i_KRC(self, indirect, address, instruction):
|
||||
self.AC |= self.kbd.read()
|
||||
self.kbd.clear()
|
||||
trace.itrace('KRC')
|
||||
return 1
|
||||
traced = trace.itrace('KRC')
|
||||
return (1, traced)
|
||||
|
||||
def i_RRB(self, indirect, address, instruction):
|
||||
self.AC |= self.ttyin.read()
|
||||
trace.itrace('RRB')
|
||||
return 1
|
||||
traced = trace.itrace('RRB')
|
||||
return (1, traced)
|
||||
|
||||
def i_RCF(self, indirect, address, instruction):
|
||||
self.ttyin.clear()
|
||||
trace.itrace('RCF')
|
||||
return 1
|
||||
traced = trace.itrace('RCF')
|
||||
return (1, traced)
|
||||
|
||||
def i_RRC(self, indirect, address, instruction):
|
||||
self.AC |= self.ttyin.read()
|
||||
self.ttyin.clear()
|
||||
trace.itrace('RRC')
|
||||
return 1
|
||||
traced = trace.itrace('RRC')
|
||||
return (1, traced)
|
||||
|
||||
def i_TPR(self, indirect, address, instruction):
|
||||
self.ttyout.write(self.AC & 0xff)
|
||||
trace.itrace('TPR')
|
||||
return 1
|
||||
traced = trace.itrace('TPR')
|
||||
return (1, traced)
|
||||
|
||||
def i_TCF(self, indirect, address, instruction):
|
||||
self.ttyout.clear()
|
||||
trace.itrace('TCF')
|
||||
return 1
|
||||
traced = trace.itrace('TCF')
|
||||
return (1, traced)
|
||||
|
||||
def i_TPC(self, indirect, address, instruction):
|
||||
self.ttyout.write(self.AC & 0xff)
|
||||
self.ttyout.clear()
|
||||
trace.itrace('TPC')
|
||||
return 1
|
||||
traced = trace.itrace('TPC')
|
||||
return (1, traced)
|
||||
|
||||
def i_HRB(self, indirect, address, instruction):
|
||||
self.AC |= self.ptrptp.read()
|
||||
trace.itrace('HRB')
|
||||
return 1
|
||||
traced = trace.itrace('HRB')
|
||||
return (1, traced)
|
||||
|
||||
def i_HOF(self, indirect, address, instruction):
|
||||
self.ptrptp.stop()
|
||||
trace.itrace('HOF')
|
||||
return 1
|
||||
traced = trace.itrace('HOF')
|
||||
return (1, traced)
|
||||
|
||||
def i_HON(self, indirect, address, instruction):
|
||||
self.ptrptp.start()
|
||||
trace.itrace('HON')
|
||||
return 1
|
||||
traced = trace.itrace('HON')
|
||||
return (1, traced)
|
||||
|
||||
def i_STB(self, indirect, address, instruction):
|
||||
trace.itrace('STB')
|
||||
return 1
|
||||
traced = trace.itrace('STB')
|
||||
return (1, traced)
|
||||
|
||||
def i_SCF(self, indirect, address, instruction):
|
||||
self.Sync40Hz = 0
|
||||
trace.itrace('SCF')
|
||||
return 1
|
||||
traced = trace.itrace('SCF')
|
||||
return (1, traced)
|
||||
|
||||
def i_IOS(self, indirect, address, instruction):
|
||||
trace.itrace('IOS')
|
||||
return 1
|
||||
traced = trace.itrace('IOS')
|
||||
return (1, traced)
|
||||
|
||||
def i_IOT101(self, indirect, address, instruction):
|
||||
trace.itrace('IOT101')
|
||||
return 1
|
||||
traced = trace.itrace('IOT101')
|
||||
return (1, traced)
|
||||
|
||||
def i_IOT111(self, indirect, address, instruction):
|
||||
trace.itrace('IOT111')
|
||||
return 1
|
||||
traced = trace.itrace('IOT111')
|
||||
return (1, traced)
|
||||
|
||||
def i_IOT131(self, indirect, address, instruction):
|
||||
trace.itrace('IOT131')
|
||||
return 1
|
||||
traced = trace.itrace('IOT131')
|
||||
return (1, traced)
|
||||
|
||||
def i_IOT132(self, indirect, address, instruction):
|
||||
trace.itrace('IOT132')
|
||||
return 1
|
||||
traced = trace.itrace('IOT132')
|
||||
return (1, traced)
|
||||
|
||||
def i_IOT134(self, indirect, address, instruction):
|
||||
trace.itrace('IOT134')
|
||||
return 1
|
||||
traced = trace.itrace('IOT134')
|
||||
return (1, traced)
|
||||
|
||||
def i_IOT141(self, indirect, address, instruction):
|
||||
trace.itrace('IOT141')
|
||||
return 1
|
||||
traced = trace.itrace('IOT141')
|
||||
return (1, traced)
|
||||
|
||||
def i_IOF(self, indirect, address, instruction):
|
||||
trace.itrace('IOF')
|
||||
return 1
|
||||
traced = trace.itrace('IOF')
|
||||
return (1, traced)
|
||||
|
||||
def i_ION(self, indirect, address, instruction):
|
||||
trace.itrace('ION')
|
||||
return 1
|
||||
traced = trace.itrace('ION')
|
||||
return (1, traced)
|
||||
|
||||
def i_PPC(self, indirect, address, instruction):
|
||||
self.ptrptp.punch(self.AC & 0xff)
|
||||
trace.itrace('PPC')
|
||||
return 1
|
||||
traced = trace.itrace('PPC')
|
||||
return (1, traced)
|
||||
|
||||
def i_PSF(self, indirect, address, instruction):
|
||||
if self.ptrptp.ready():
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('PSF')
|
||||
return 1
|
||||
traced = trace.itrace('PSF')
|
||||
return (1, traced)
|
||||
|
||||
def i_RAL1(self, indirect, address, instruction):
|
||||
newl = self.AC >> 15
|
||||
newac = (self.AC << 1) | self.L
|
||||
self.L = newl
|
||||
self.AC = newac & WORDMASK
|
||||
trace.itrace('RAL', False, 1)
|
||||
return 1
|
||||
traced = trace.itrace('RAL', False, 1)
|
||||
return (1, traced)
|
||||
|
||||
def i_RAL2(self, indirect, address, instruction):
|
||||
newl = self.AC >> 15
|
||||
@@ -489,8 +491,8 @@ class MainCPU(object):
|
||||
newac = (self.AC << 1) | self.L
|
||||
self.L = newl
|
||||
self.AC = newac & WORDMASK
|
||||
trace.itrace('RAL', False, 2)
|
||||
return 1
|
||||
traced = trace.itrace('RAL', False, 2)
|
||||
return (1, traced)
|
||||
|
||||
def i_RAL3(self, indirect, address, instruction):
|
||||
newl = self.AC >> 15
|
||||
@@ -505,16 +507,16 @@ class MainCPU(object):
|
||||
newac = (self.AC << 1) | self.L
|
||||
self.L = newl
|
||||
self.AC = newac & WORDMASK
|
||||
trace.itrace('RAL', False, 3)
|
||||
return 1
|
||||
traced = trace.itrace('RAL', False, 3)
|
||||
return (1, traced)
|
||||
|
||||
def i_RAR1(self, indirect, address, instruction):
|
||||
newl = self.AC & 1
|
||||
newac = (self.AC >> 1) | (self.L << 15)
|
||||
self.L = newl
|
||||
self.AC = newac & WORDMASK
|
||||
trace.itrace('RAR', False, 1)
|
||||
return 1
|
||||
traced = trace.itrace('RAR', False, 1)
|
||||
return (1, traced)
|
||||
|
||||
def i_RAR2(self, indirect, address, instruction):
|
||||
newl = self.AC & 1
|
||||
@@ -525,8 +527,8 @@ class MainCPU(object):
|
||||
newac = (self.AC >> 1) | (self.L << 15)
|
||||
self.L = newl
|
||||
self.AC = newac & WORDMASK
|
||||
trace.itrace('RAR', False, 2)
|
||||
return 1
|
||||
traced = trace.itrace('RAR', False, 2)
|
||||
return (1, traced)
|
||||
|
||||
def i_RAR3(self, indirect, address, instruction):
|
||||
newl = self.AC & 1
|
||||
@@ -541,162 +543,162 @@ class MainCPU(object):
|
||||
newac = (self.AC >> 1) | (self.L << 15)
|
||||
self.L = newl
|
||||
self.AC = newac & WORDMASK
|
||||
trace.itrace('RAR', False, 3)
|
||||
return 1
|
||||
traced = trace.itrace('RAR', False, 3)
|
||||
return (1, traced)
|
||||
|
||||
def i_SAL1(self, indirect, address, instruction):
|
||||
high_bit = self.AC & HIGHBITMASK
|
||||
value = self.AC & 037777
|
||||
self.AC = (value << 1) | high_bit
|
||||
trace.itrace('SAL', False, 1)
|
||||
return 1
|
||||
traced = trace.itrace('SAL', False, 1)
|
||||
return (1, traced)
|
||||
|
||||
def i_SAL2(self, indirect, address, instruction):
|
||||
high_bit = self.AC & HIGHBITMASK
|
||||
value = self.AC & 017777
|
||||
self.AC = (value << 2) | high_bit
|
||||
trace.itrace('SAL', False, 2)
|
||||
return 1
|
||||
traced = trace.itrace('SAL', False, 2)
|
||||
return (1, traced)
|
||||
|
||||
def i_SAL3(self, indirect, address, instruction):
|
||||
high_bit = self.AC & HIGHBITMASK
|
||||
value = self.AC & 007777
|
||||
self.AC = (value << 3) | high_bit
|
||||
trace.itrace('SAL', False, 3)
|
||||
return 1
|
||||
traced = trace.itrace('SAL', False, 3)
|
||||
return (1, traced)
|
||||
|
||||
def i_SAR1(self, indirect, address, instruction):
|
||||
high_bit = self.AC & HIGHBITMASK
|
||||
self.AC = (self.AC >> 1) | high_bit
|
||||
trace.itrace('SAR', False, 1)
|
||||
return 1
|
||||
traced = trace.itrace('SAR', False, 1)
|
||||
return (1, traced)
|
||||
|
||||
def i_SAR2(self, indirect, address, instruction):
|
||||
high_bit = self.AC & HIGHBITMASK
|
||||
self.AC = (self.AC >> 1) | high_bit
|
||||
self.AC = (self.AC >> 1) | high_bit
|
||||
trace.itrace('SAR', False, 2)
|
||||
return 1
|
||||
traced = trace.itrace('SAR', False, 2)
|
||||
return (1, traced)
|
||||
|
||||
def i_SAR3(self, indirect, address, instruction):
|
||||
high_bit = self.AC & HIGHBITMASK
|
||||
self.AC = (self.AC >> 1) | high_bit
|
||||
self.AC = (self.AC >> 1) | high_bit
|
||||
self.AC = (self.AC >> 1) | high_bit
|
||||
trace.itrace('SAR', False, 3)
|
||||
return 1
|
||||
traced = trace.itrace('SAR', False, 3)
|
||||
return (1, traced)
|
||||
|
||||
def i_DON(self, indirect, address, instruction):
|
||||
self.displaycpu.DRSindex = 0
|
||||
self.displaycpu.start()
|
||||
trace.itrace('DON')
|
||||
return 1
|
||||
traced = trace.itrace('DON')
|
||||
return (1, traced)
|
||||
|
||||
def i_ASZ(self):
|
||||
if self.AC == 0:
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('ASZ')
|
||||
return 1
|
||||
traced = trace.itrace('ASZ')
|
||||
return (1, traced)
|
||||
|
||||
def i_ASN(self):
|
||||
if self.AC != 0:
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('ASN')
|
||||
return 1
|
||||
traced = trace.itrace('ASN')
|
||||
return (1, traced)
|
||||
|
||||
def i_ASP(self):
|
||||
if not (self.AC & HIGHBITMASK):
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('ASP')
|
||||
return 1
|
||||
traced = trace.itrace('ASP')
|
||||
return (1, traced)
|
||||
|
||||
def i_ASM(self):
|
||||
if (self.AC & HIGHBITMASK):
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('ASM')
|
||||
return 1
|
||||
traced = trace.itrace('ASM')
|
||||
return (1, traced)
|
||||
|
||||
def i_LSZ(self):
|
||||
if self.L == 0:
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('LSZ')
|
||||
return 1
|
||||
traced = trace.itrace('LSZ')
|
||||
return (1, traced)
|
||||
|
||||
def i_LSN(self):
|
||||
if self.L != 0:
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('LSN')
|
||||
return 1
|
||||
traced = trace.itrace('LSN')
|
||||
return (1, traced)
|
||||
|
||||
def i_DSF(self):
|
||||
if self.displaycpu.ison():
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('DSF')
|
||||
return 1
|
||||
traced = trace.itrace('DSF')
|
||||
return (1, traced)
|
||||
|
||||
def i_DSN(self):
|
||||
if not self.displaycpu.ison():
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('DSN')
|
||||
return 1
|
||||
traced = trace.itrace('DSN')
|
||||
return (1, traced)
|
||||
|
||||
def i_KSF(self):
|
||||
if self.kbd.ready():
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('KSF')
|
||||
return 1
|
||||
traced = trace.itrace('KSF')
|
||||
return (1, traced)
|
||||
|
||||
def i_KSN(self):
|
||||
if not self.kbd.ready():
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('KSN')
|
||||
return 1
|
||||
traced = trace.itrace('KSN')
|
||||
return (1, traced)
|
||||
|
||||
def i_RSF(self):
|
||||
if self.ttyin.ready():
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('RSF')
|
||||
return 1
|
||||
traced = trace.itrace('RSF')
|
||||
return (1, traced)
|
||||
|
||||
def i_RSN(self):
|
||||
if not self.ttyin.ready():
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('RSN')
|
||||
return 1
|
||||
traced = trace.itrace('RSN')
|
||||
return (1, traced)
|
||||
|
||||
def i_TSF(self):
|
||||
if self.ttyout.ready():
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('TSF')
|
||||
return 1
|
||||
traced = trace.itrace('TSF')
|
||||
return (1, traced)
|
||||
|
||||
def i_TSN(self):
|
||||
if not self.ttyout.ready():
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('TSN')
|
||||
return 1
|
||||
traced = trace.itrace('TSN')
|
||||
return (1, traced)
|
||||
|
||||
def i_SSF(self):
|
||||
if self.display.ready(): # skip if 40Hz sync on
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('SSF')
|
||||
return 1
|
||||
traced = trace.itrace('SSF')
|
||||
return (1, traced)
|
||||
|
||||
def i_SSN(self):
|
||||
if not self.display.ready():
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('SSN')
|
||||
return 1
|
||||
traced = trace.itrace('SSN')
|
||||
return (1, traced)
|
||||
|
||||
def i_HSF(self):
|
||||
if self.ptrptp.ready():
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('HSF')
|
||||
return 1
|
||||
traced = trace.itrace('HSF')
|
||||
return (1, traced)
|
||||
|
||||
def i_HSN(self):
|
||||
if not self.ptrptp.ready():
|
||||
self.PC = (self.PC + 1) & WORDMASK
|
||||
trace.itrace('HSN')
|
||||
return 1
|
||||
traced = trace.itrace('HSN')
|
||||
return (1, traced)
|
||||
|
||||
|
||||
@@ -263,6 +263,7 @@ class Memory(object):
|
||||
|
||||
try:
|
||||
self.memory[address] = MASK_16(value)
|
||||
print('Memory: setting address %06o to %06o' % (address, MASK_16(value)))
|
||||
except IndexError:
|
||||
raise RuntimeError('Bad address: %06o (max mem=%06o, ADDRMASK=%06o)'
|
||||
% (address, len(self.memory), ADDRMASK))
|
||||
|
||||
@@ -12,6 +12,7 @@ Based on the 'borg' recipe from [http://code.activestate.com/recipes/66531/].
|
||||
"""
|
||||
|
||||
import os
|
||||
import collections
|
||||
|
||||
from Globals import *
|
||||
|
||||
@@ -44,6 +45,13 @@ class Trace(object):
|
||||
self.cpu = maincpu
|
||||
self.dcpu = displaycpu
|
||||
|
||||
self.trace_map = collections.defaultdict(bool)
|
||||
|
||||
def set_trace_map(self, trace_map):
|
||||
"""Set the trace address dict mapping."""
|
||||
|
||||
self.trace_map = trace_map
|
||||
|
||||
def add_maincpu(self, maincpu):
|
||||
"""Add the main CPU object."""
|
||||
|
||||
@@ -91,16 +99,24 @@ class Trace(object):
|
||||
|
||||
opcode the main CPU opcode
|
||||
indirect True if instruction was indirect
|
||||
adress address for the instruction (if any)
|
||||
address address for the instruction (if any)
|
||||
|
||||
Returns True if tracing, else False.
|
||||
"""
|
||||
|
||||
if self.tracing:
|
||||
# print('itrace: self.cpu.PC=%06o, self.trace_map[self.cpu.PC]=%s'
|
||||
# % (self.cpu.PC-1, str(self.trace_map[self.cpu.PC-1])))
|
||||
|
||||
if self.tracing and self.trace_map[self.cpu.PC-1]:
|
||||
char = '*' if indirect else ''
|
||||
if address is None:
|
||||
self.tracefile.write('%s\t%s\t' % (opcode, char))
|
||||
else:
|
||||
self.tracefile.write('%s\t%s%5.5o\t' % (opcode, char, address))
|
||||
self.tracefile.flush()
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def itraceend(self, dispon):
|
||||
"""Trace at the end of one execution cycle.
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# test of loading simple code and dumping memory
|
||||
bootrom ptr; mount ptr dumpmem_test.ptp; setreg pc 040; rununtil 0; dumpmem dumpmem_test.dump
|
||||
bootrom ptr; mount ptr dumpmem_test.ptp; setreg pc 040; trace 040,077; rununtil 0; dumpmem dumpmem_test.dump
|
||||
|
||||
128
pymlac/pymlac
128
pymlac/pymlac
@@ -22,10 +22,10 @@ required. The options are:
|
||||
-ptr <file> loads a file on to the papertape reader device
|
||||
-r (<address> | pc) executes from <address> or the current PC contents
|
||||
-s <setfile> sets memory adress values from <setfile>
|
||||
-t (<addr1> [,<addr2>] | off) controls the execution trace:
|
||||
-t 0100 trace from address 0100 (octal)
|
||||
-t 0100,200 trace from 0100 octal to 200 decimal
|
||||
-t off turns trace off
|
||||
-t (<range>[:<range>] | off) controls the execution trace:
|
||||
-t 0100,0200 trace from 0100 octal to 200 decimal
|
||||
-t 0100,0200:0210,0300 trace from 0100 to 0200 and 0210 to 0300
|
||||
-t off turns trace off
|
||||
-ttyin <file> loads a file on to the teletype reader device
|
||||
-ttyout <file> loads a file on to the teletype writer device
|
||||
-v <viewfile> views contents of memory addresses from file
|
||||
@@ -36,10 +36,21 @@ required. The options are:
|
||||
|
||||
import sys
|
||||
import getopt
|
||||
import collections
|
||||
|
||||
from Globals import *
|
||||
import MainCPU
|
||||
import Memory
|
||||
import PtrPtp
|
||||
import TtyIn
|
||||
import TtyOut
|
||||
import Trace
|
||||
|
||||
trace = Trace.Trace(TRACE_FILENAME)
|
||||
|
||||
|
||||
def str2int(s):
|
||||
"""Convert a strinf to an integer value.
|
||||
"""Convert a string to an integer value.
|
||||
|
||||
s the string to convert
|
||||
|
||||
@@ -47,8 +58,16 @@ def str2int(s):
|
||||
None is returned if the string cannot be converted.
|
||||
"""
|
||||
|
||||
return None
|
||||
base = 10
|
||||
if s[0] == '0':
|
||||
base = 8
|
||||
|
||||
try:
|
||||
value = int(s, base=base)
|
||||
except:
|
||||
return None
|
||||
|
||||
return value
|
||||
|
||||
def usage(msg=None):
|
||||
if msg:
|
||||
@@ -58,13 +77,40 @@ def usage(msg=None):
|
||||
print(__doc__)
|
||||
|
||||
|
||||
def start_running(cpu, memory, ptrptp):
|
||||
"""Run the Imlac machine until it stops."""
|
||||
|
||||
cpu.running = True
|
||||
while cpu.running:
|
||||
(cycles, traced) = cpu.execute_one_instruction()
|
||||
if traced:
|
||||
trace.itraceend(False)
|
||||
ptrptp.ptr_tick(cycles)
|
||||
ptrptp.ptp_tick(cycles)
|
||||
|
||||
def main():
|
||||
"""Main function of the simulator. Mostly interpret CLI args."""
|
||||
|
||||
# prepare the Imlac machine
|
||||
imlac_memory = Memory.Memory()
|
||||
imlac_ptrptp = PtrPtp.PtrPtp()
|
||||
imlac_ttyin = TtyIn.TtyIn()
|
||||
imlac_ttyout = TtyOut.TtyOut()
|
||||
imlac_cpu = MainCPU.MainCPU(imlac_memory, None, None,
|
||||
None, imlac_ttyin, imlac_ttyout, imlac_ptrptp)
|
||||
imlac_cpu.running = True
|
||||
imlac_display_state = False
|
||||
|
||||
# prepare the trace
|
||||
trace.add_maincpu(imlac_cpu)
|
||||
|
||||
print('sys.argv=%s' % str(sys.argv))
|
||||
|
||||
len_sys_argv = len(sys.argv)
|
||||
# trace_map defines addresses we are tracing at
|
||||
# initially, no tracing
|
||||
trace_map = collections.defaultdict(bool)
|
||||
|
||||
len_sys_argv = len(sys.argv)
|
||||
ndx = 1
|
||||
while ndx < len_sys_argv:
|
||||
opt = sys.argv[ndx]
|
||||
@@ -80,23 +126,28 @@ def main():
|
||||
dev = sys.argv[ndx].lower()
|
||||
ndx += 1
|
||||
if dev == 'ptr':
|
||||
set_bootrom('PTR')
|
||||
# set_bootrom('PTR')
|
||||
imlac_memory.set_ROM('ptr')
|
||||
elif dev == 'tty':
|
||||
set_bootrom('TTYIN')
|
||||
# set_bootrom('TTYIN')
|
||||
imlac_memory.set_ROM('tty')
|
||||
elif dev == 'none':
|
||||
set_bootrom(None)
|
||||
# set_bootrom(None)
|
||||
imlac_memory.set_ROM(None)
|
||||
else:
|
||||
usage("-b option must be followed by 'ptr', 'tty' or 'none'")
|
||||
sys.exit(10)
|
||||
elif opt == '-c':
|
||||
clear_core()
|
||||
# clear_core()
|
||||
imlac_memory.clear_core()
|
||||
elif opt == '-cf':
|
||||
if ndx >= len_sys_argv:
|
||||
usage("'-cf' option needs a following filename")
|
||||
sys.exit(10)
|
||||
filename = sys.argv[ndx]
|
||||
ndx += 1
|
||||
set_core_file(filename)
|
||||
# set_core_file(filename)
|
||||
imlac_memory.set_corefile(filename)
|
||||
elif opt == '-d':
|
||||
if ndx >= len_sys_argv:
|
||||
usage("'-d' option needs a following data switch value")
|
||||
@@ -106,7 +157,8 @@ def main():
|
||||
if value is None:
|
||||
usage("The '-d' option must be followed by a decimal or octal value")
|
||||
sys.exit(10)
|
||||
set_data_switch(value)
|
||||
# set_data_switch(value)
|
||||
imlac_cpu.DS = value
|
||||
elif opt == '-h':
|
||||
usage()
|
||||
sys.exit(0)
|
||||
@@ -116,14 +168,16 @@ def main():
|
||||
sys.exit(10)
|
||||
filename = sys.argv[ndx]
|
||||
ndx += 1
|
||||
set_ptp_filename(filename)
|
||||
# set_ptp_filename(filename)
|
||||
imlac_ptrptp.ptp_mount(filename)
|
||||
elif opt == '-ptr':
|
||||
if ndx >= len_sys_argv:
|
||||
usage("'-ptr' option needs a following PTR filename")
|
||||
sys.exit(10)
|
||||
filename = sys.argv[ndx]
|
||||
ndx += 1
|
||||
set_ptr_filename(filename)
|
||||
# set_ptr_filename(filename)
|
||||
imlac_ptrptp.ptr_mount(filename)
|
||||
elif opt == '-r':
|
||||
if ndx >= len_sys_argv:
|
||||
usage("'-r' option needs a following address or 'pc'")
|
||||
@@ -135,8 +189,10 @@ def main():
|
||||
if addr_value is None:
|
||||
usage("'-r' option needs a following address or 'pc'")
|
||||
sys.exit(10)
|
||||
set_pc(addr_value)
|
||||
start_running()
|
||||
# set_pc(addr_value)
|
||||
imlac_cpu.PC = addr_value
|
||||
trace.set_trace_map(trace_map)
|
||||
start_running(imlac_cpu, imlac_memory, imlac_ptrptp)
|
||||
elif opt == '-s':
|
||||
if ndx >= len_sys_argv:
|
||||
usage("'-s' option needs a following data filename")
|
||||
@@ -146,39 +202,44 @@ def main():
|
||||
set_mem_from_file(filename)
|
||||
elif opt == '-t':
|
||||
if ndx >= len_sys_argv:
|
||||
usage("'-t' option needs a following address range or 'off'")
|
||||
usage("'-t' option needs following address ranges or 'off'")
|
||||
sys.exit(10)
|
||||
r = sys.argv[ndx]
|
||||
ndx += 1
|
||||
if r == 'off':
|
||||
set_trace_off()
|
||||
trace_map = collections.defaultdict(bool)
|
||||
else:
|
||||
if ',' in r:
|
||||
rr = r.split(',')
|
||||
if len(rr) != 2:
|
||||
usage("'-r' option may be followed by only two addresses")
|
||||
trace_map = collections.defaultdict(bool)
|
||||
print('r=%s' % r)
|
||||
for rng in r.split(':'):
|
||||
print('rng=%s' % rng)
|
||||
be = rng.split(',')
|
||||
print('be=%s' % str(be))
|
||||
if len(be) != 2:
|
||||
usage("'-r' ranges must have form 'begin,end'")
|
||||
sys.exit(10)
|
||||
(start, stop) = rr
|
||||
start_addr = str2int(start)
|
||||
stop_addr = str2int(stop)
|
||||
else:
|
||||
start_addr = str2int(r)
|
||||
stop_addr = None
|
||||
set_trace_on(star_addr, stop_addr)
|
||||
(begin, end) = be
|
||||
begin = str2int(begin)
|
||||
end = str2int(end)
|
||||
print('begin=%s, end=%s' % (str(begin), str(end)))
|
||||
for addr in range(begin, end+1):
|
||||
trace_map[addr] = True
|
||||
elif opt == '-ttyin':
|
||||
if ndx >= len_sys_argv:
|
||||
usage("'-ttyin' option needs a following data filename")
|
||||
sys.exit(10)
|
||||
filename = sys.argv[ndx]
|
||||
ndx += 1
|
||||
set_tty_in(filename)
|
||||
# set_tty_in(filename)
|
||||
imlac_ttyin.mount(filename)
|
||||
elif opt == '-ttyout':
|
||||
if ndx >= len_sys_argv:
|
||||
usage("'-ttyout' option needs a following data filename")
|
||||
sys.exit(10)
|
||||
filename = sys.argv[ndx]
|
||||
ndx += 1
|
||||
set_tty_out(filename)
|
||||
# set_tty_out(filename)
|
||||
imlac_ttyout.mount(filename)
|
||||
elif opt == '-v':
|
||||
if ndx >= len_sys_argv:
|
||||
usage("'-v' option needs a following address filename")
|
||||
@@ -199,7 +260,8 @@ def main():
|
||||
else:
|
||||
usage("'-v' option needs a following 'on' or 'off'")
|
||||
sys.exit(10)
|
||||
set_rom_write(state)
|
||||
# set_rom_write(state)
|
||||
imlac_memory.set_ROM_writable(state)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -12,6 +12,7 @@ where <filename> is a file of test instructions and
|
||||
"""
|
||||
|
||||
import time
|
||||
import collections
|
||||
|
||||
# We implement a small interpreter to test the CPU.
|
||||
# The DSL is documented here: [github.com/rzzzwilson/pymlac].
|
||||
@@ -146,6 +147,7 @@ class TestCPU(object):
|
||||
# dismount <device>
|
||||
# checkfile <file1> <file2>
|
||||
# dumpmem file begin,end
|
||||
# cmpmem file
|
||||
|
||||
def setreg(self, name, value):
|
||||
"""Set register to a value.
|
||||
@@ -387,7 +389,7 @@ class TestCPU(object):
|
||||
else:
|
||||
return 'mount: bad device: %s' % device
|
||||
|
||||
def dismount(self, device):
|
||||
def dismount(self, device, ignore):
|
||||
"""Dismount a file from a device.
|
||||
|
||||
device name of device
|
||||
@@ -441,6 +443,9 @@ class TestCPU(object):
|
||||
with open(filename, 'wb') as handle:
|
||||
json.dump(mem, handle)
|
||||
|
||||
def cmpmem(self, filename, ignore):
|
||||
pass
|
||||
|
||||
# end of DSL primitives
|
||||
|
||||
def check_all_mem(self):
|
||||
@@ -597,7 +602,9 @@ class TestCPU(object):
|
||||
elif opcode == 'checkfile':
|
||||
r = self.checkfile(fld1, fld2)
|
||||
elif opcode == 'dumpmem':
|
||||
r = self.checkfile(fld1, fld2)
|
||||
r = self.dumpmem(fld1, fld2)
|
||||
elif opcode == 'cmpmem':
|
||||
r = self.cmpmem(fld1, fld2)
|
||||
else:
|
||||
print("Unrecognized opcode '%s' in: %s" % (opcode, test))
|
||||
raise Exception("Unrecognized opcode '%s' in: %s" % (opcode, test))
|
||||
|
||||
Reference in New Issue
Block a user