1
0
mirror of https://github.com/rzzzwilson/pymlac.git synced 2025-06-10 09:32:41 +00:00
rzzzwilson.pymlac/pymlac/DisplayCPU.py
2015-06-18 13:19:44 +07:00

331 lines
6.9 KiB
Python

#!/usr/bin/python
"""
The Imlac display CPU.
"""
import sys
from Globals import *
import Trace
# display CPU constants
MODE_NORMAL = 0
MODE_DEIM = 1
######
# The Display CPU registers
######
DPC = 0 # display CPU program counter
DRS = [0, 0, 0, 0, 0, 0, 0, 0] # display CPU ???
DRSindex = 0 # display CPU ???
DIB = 0 # display CPU ???
DX = 0 # display CPU draw X register
DY = 0 # display CPU draw Y register
# global state variables
Mode = MODE_NORMAL
Running = False
def init():
global Mode, Running
Mode = MODE_NORMAL
Running = False
def DEIMdecode(byte):
"""Decode a DEIM byte"""
result = ''
if byte & 0x80:
if byte & 0x40: result += 'B'
else: result += 'D'
if byte & 0x20: result += '-'
result += '%d' % ((byte >> 3) & 0x03)
if byte & 0x04: result += '-'
result += '%d' % (byte & 0x03)
else:
if byte == 0111: result += 'N'
elif byte == 0151: result += 'R'
elif byte == 0171: result += 'F'
elif byte == 0200: result += 'P'
else: result += 'A%3.3o' % byte
return result
def doDEIMByte(byte):
global DPC, DX, DY, DRSindex
global Mode
if byte & 0x80: # increment?
prevDX = DX
prevDY = DY
if byte & 0x20:
DX -= (byte & 0x18) >> 3
else:
DX += (byte & 0x18) >> 3
if byte & 0x04:
DY -= (byte & 0x03)
else:
DY += (byte & 0x03)
if byte & 0x40:
display.draw(0, prevDX, prevDY, DX, DY)
else: # micro instructions
if byte & 0x40:
Mode = MODE_NORMAL
if byte & 0x20: # DRJM
if DRSindex <= 0:
Trace.comment('\nDRS stack underflow at display address %6.6o'
% (DPC - 1))
illegal()
DRSindex -= 1
DPC = DRS[DRSindex]
if byte & 0x10:
DX += 0x08
if byte & 0x08:
DX &= 0xfff8
if byte & 0x02:
DY += 0x10
if byte & 0x01:
DY &= 0xfff0
def execute_one_instruction():
global DPC
global Mode
if not Running:
Trace.dtrace('')
return 0
instruction = Memory.get(DPC, 0)
DPC = MASK_MEM(DPC + 1)
if Mode == MODE_DEIM:
Trace.trace(DEIMdecode(instruction >> 8) + '\t')
doDEIMByte(instruction >> 8)
if Mode == MODE_DEIM:
Trace.trace(DEIMdecode(instruction & 0xff) + '\t')
doDEIMByte(instruction & 0xff)
else:
Trace.trace('\t')
return 1
opcode = instruction >> 12
address = instruction & 007777
if opcode == 000: return page00(instruction)
elif opcode == 001: return i_DLXA(address)
elif opcode == 002: return i_DLYA(address)
elif opcode == 003: return i_DEIM(address)
elif opcode == 004: return i_DLVH(address)
elif opcode == 005: return i_DJMS(address)
elif opcode == 006: return i_DJMP(address)
elif opcode == 007: illegal(instruction)
else: illegal(instruction)
def illegal(instruction=None):
if instruction:
Trace.comment('Illegal display instruction (%6.6o) at address %6.6o'
% (instruction, (DPC - 1)))
else:
Trace.comment('Illegal display instruction at address %6.6o'
% (DPC - 1))
sys.exit(0)
def ison():
return Running
def i_DDXM():
global DX
DX -= 040
Trace.dtrace('DDXM')
def i_DDYM():
global DY
DY -= 040
Trace.dtrace('DDYM')
def i_DEIM(address):
global Mode
Mode = MODE_DEIM
Trace.deimtrace('DEIM', DEIMdecode(address & 0377))
doDEIMByte(address & 0377)
return 1
def i_DHLT():
Running = False
Trace.dtrace('DHLT')
def i_DHVC():
Trace.dtrace('DHVC')
def i_DIXM():
global DX
DX += 04000
Trace.dtrace('DIXM')
def i_DIYM():
global DY
DY += 04000
Trace.dtrace('DIYM')
def i_DJMP(address):
global DPC, DIB
DPC = MASK_MEM(address + (DIB << 12))
Trace.dtrace('DJMP', address)
return 1
def i_DJMS(address):
global DPC, DRSindex, DIB
if DRSindex >= 8:
Trace.comment('DRS stack overflow at display address %6.6o'
% (DPC - 1))
illegal()
DRS[DRSindex] = DPC
DRSindex += 1
DPC = MASK_MEM(address + (DIB << 12))
Trace.dtrace('DJMS', address)
return 1
def i_DLXA(address):
global DX
DX = address
Trace.dtrace('DLXA', address)
return 1
def i_DLYA(address):
global DY
DY = address
Trace.dtrace('DLYA', address)
return 1
def i_DLVH(word1):
global DPC, DX, DY
word2 = Memory.get(DPC, 0)
DPC = MASK_MEM(DPC + 1)
word3 = Memory.get(DPC, 0)
DPC = MASK_MEM(DPC + 1)
dotted = word2 & 040000
beamon = word2 & 020000
negx = word3 & 040000
negy = word3 & 020000
ygtx = word3 & 010000
M = word2 & 007777
N = word3 & 007777
prevDX = DX
prevDY = DY
if ygtx: # M is y, N is x
if negx:
DX -= N
else:
DX += N
if negy:
DY -= M
else:
DY += M
else: # M is x, N is y
if negx:
DX -= M
else:
DX += M
if negy:
DY -= N
else:
DY += N
display.draw(dotted, prevDX, prevDY, DX, DY)
Trace.dtrace('DLVH')
return 3
def i_DRJM():
global DPC, DRSindex
if DRSindex <= 0:
Trace.comment('DRS stack underflow at display address %6.6o'
% (DPC - 1))
illegal()
DRSindex -= 1
DPC = DRS[DRSindex]
Trace.dtrace('DRJM')
def i_DSTB(block):
global DIB
DIB = block
Trace.dtrace('DSTB\t%d' % block)
def i_DSTS(scale):
global Scale
if scale == 0:
Scale = 0.5
elif scale == 1:
Scale = 1.0
elif scale == 2:
Scale = 2.0
elif scale == 3:
Scale = 3.0
else:
illegal()
Trace.dtrace('DSTS', scale)
def page00(instruction):
if instruction == 000000: # DHLT
i_DHLT()
elif instruction == 004000: # DNOP
Trace.dtrace('DNOP')
elif instruction == 004004: # DSTS 0
i_DSTS(0)
elif instruction == 004005: # DSTS 1
i_DSTS(1)
elif instruction == 004006: # DSTS 2
i_DSTS(2)
elif instruction == 004007: # DSTS 3
i_DSTS(3)
elif instruction == 004010: # DSTB 0
i_DSTB(0)
elif instruction == 004011: # DSTB 1
i_DSTB(1)
elif instruction == 004040: # DRJM
i_DRJM()
elif instruction == 004100: # DDYM
i_DDYM()
elif instruction == 004200: # DDXM
i_DDXM()
elif instruction == 004400: # DIYM
i_DIYM()
elif instruction == 005000: # DIXM
i_DIXM()
elif instruction == 006000: # DHVC
i_DHVC()
else:
illegal(instruction)
return 1
def start():
global Running
Running = True
def stop():
global Running
Running = False