Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #-------------------------------------------------------------------------------
- # Name: up8085
- # Purpose: Emulate the Dynalog microfriend 8085 microprocessor
- #
- # Author: Aditya Sriram
- # Version: 1.0
- # Created: 31/01/2013
- # Copyright: (c) Cubes and Codes 2013
- # Licence: GNU General Public License
- #
- # View <http://www.youtube.com/watch?v=k8kqdx--SLg> for a demonstration
- # of this program
- #-------------------------------------------------------------------------------
- #!/usr/bin/env python
- #============================== External Modules ===============================
- from Tkinter import *
- import re, pickle, os, win32api
- from led import LED
- #-------------------------------------------------------------------------------
- #============================ Opcode initialization ============================
- OpCode = pickle.load(open(os.path.join(os.getcwd(), 'OpcodeSheet.pkl')))
- #-------------------------------------------------------------------------------
- #============================ Memory and Registers =============================
- reg = dict(zip('abcdefhlm',[0x0 for i in 'abcdefhlm']))
- mem = {'c000':0x0}
- flags = {'s':0,'z':0,'ac':0,'p':0,'cy':0,'-':0}
- regPairs = {'h':'l','b':'c','d':'e'}
- #-------------------------------------------------------------------------------
- #============================== General Functions ==============================
- def hexStr(n,fill=2):
- return hex(n).replace('0x','').zfill(fill)
- #-------------------------------------------------------------------------------
- #============================== Class Definitons ===============================
- class Button:
- text = ""
- subText = ""
- key = ""
- master = None
- canvas = None
- def __init__(self, master, buttonText, locX, locY, width, height, clickFunc):
- self.canvas = Canvas(master, background='#3C3C3C', height=height, width=width, cursor="hand2")
- self.canvas.place(x=locX, y=locY)
- self.canvas.create_text(width/2, height/2,
- font=("Monaco",min(height, width)/3-10),
- text=buttonText, fill='white', justify=CENTER)
- buttonText = buttonText.split('\n')
- self.text = buttonText[0]
- if len(buttonText) > 1:
- self.subText = buttonText[1]
- self.key = self.text.lower()
- self.master = master
- self.canvas.bind('<Enter>', lambda e: self.canvas.config(background='#222222'))
- self.canvas.bind('<Leave>', lambda e: self.canvas.config(background='#3C3C3C'))
- self.canvas.bind('<Button-1>', lambda e: clickFunc(self.key))
- class counter:
- address = ""
- def __init__(self, address):
- self.address = address
- def next(self, increment = 1):
- self.address = hexStr(eval('0x' + self.address) + increment, 4)
- print self.address
- def __call__(self):
- return self.address
- def value(self):
- return eval('0x' + self.address)
- #-------------------------------------------------------------------------------
- #======================== Execution assisting functions ========================
- def flagUpdate(affect = 'szpcy',register = 'a'):
- """Updates flags according to current accumulator content.(excluding
- auxiliary carry flag)"""
- global reg,flags
- acc = reg[register]
- flags['s'] = 0b1 if (('s' in affect) and (acc < 0)) else 0b0
- flags['z'] = 0b1 if (('z' in affect) and (acc == 0)) else 0b0
- if (('cy' in affect) and (acc >= 256)):
- flags['cy'] = 0b1
- reg[register] = eval('0b' + bin(acc)[-8:])
- acc = reg[register]
- else:flags['cy'] = 0b0
- if ('p' in affect):
- flags['p'] = 0b1
- for i in bin(acc)[bin(acc).index('b')+1:]:
- if i == '1':
- flags['p'] = eval(bin(not flags['p']))
- def negate(number):
- number = bin(number).replace('0b','').zfill(8)
- number = number.replace('1','*1').replace('0','1').replace('*1','0')
- return eval('0b' + number)
- def move(rd,rs):
- """MOV,MVI command"""
- global mem,reg
- rd = rd.lower()
- if rd in reg and rs in reg:
- rs =rs.lower()
- if (rd == 'm') ^ (rs =='m'):
- if rd =='m':
- mem[hexStr(reg['h'])+hexStr(reg['l'])] = reg[rs]
- else:
- reg[rd] = mem[hexStr(reg['h'])+hexStr(reg['l'])]
- elif rd != 'm':
- reg[rd] = reg[rs]
- else: pass
- else:
- reg[rd] =rs
- def add(operand,cy,operated = 'a'):
- """Operates(adds) on operand provide, with or without carry
- depending on value of carry(0:w/o,1:w/). Result is in accumulator"""
- global mem,reg,flags
- if operand == 'm':operand = mem[hexStr(reg['h']) + hexStr(reg['l'])]
- if operand in reg:operand = reg[operand]
- if (((reg[operated] % 16) + (operand % 16)) >= 16):flags['ac']=0b1
- reg[operated] = reg[operated] + operand + cy*flags['cy']
- flagUpdate('szpcy')
- def sub(operand,borrow,operated = 'a'):
- if operand == 'm':operand = mem[hexStr(reg['h']) + hexStr(reg['l'])]
- if operand in reg:
- operand = reg[operand]
- operand = negate(operand + borrow*flags['cy']) + 1
- add(operand,0,operated)
- flags['cy'] = eval(bin(not(flags['cy'])))
- flags['s'] = flags['cy']
- def bit(oper,rs):
- """Return bitwise operation result of accumulator and register or data
- oper can be:
- 0: bit-wise 'and'
- 1: bit-wise 'or'
- 2: bit-wise 'exor'"""
- global reg,flags
- operlist = [lambda x,y:x&y, lambda x,y:x|y, lambda x,y:x^y]
- if rs in reg:
- if rs == 'm':
- rs = mem[hexStr(reg['h'])+hexStr(reg['l'])]
- bit(oper,rs)
- else:
- reg['a'] = operlist[oper](reg['a'],reg[rs])
- else:
- reg['a'] = operlist[oper](reg['a'],rs)
- #============================= Executing function ==============================
- def execute(start):
- global mem,reg,flags,regPairs
- pc = counter(start)
- from time import time
- t = time()
- def getAddr(startFrom):
- """Extract 4 byte address from address locations proceeding given
- startFrom location, lsb then msb"""
- return (hexStr(mem[hexStr(startFrom.value() + 2, 4)]) + hexStr(mem[hexStr(startFrom.value() + 1, 4)]))
- while mem[pc()] != 0xcf and (time()-t) <= 15:
- operation = OpCode[mem[pc()]].lower()
- jump = [i in operation for i in ['jz','jnz','jc','jnc','jpe','jpo','jm','jp']]
- if 'mov' in operation:
- move(operation[operation.index(',')-1],operation[-1])
- elif 'mvi' in operation:
- pc.next()
- move(operation[operation.index(',')-1],mem[pc()])
- elif 'lxi' in operation:
- pc.next()
- move(regPairs[operation[-1]],mem[pc()])
- pc.next()
- move(operation[-1],mem[pc()])
- elif 'lda' in operation:
- move('a', mem[getAddr(pc)])
- pc.next(2)
- elif 'sta' in operation:
- mem[getAddr(pc)] = reg['a']
- pc.next(2)
- elif 'lhld' in operation:
- reg['l'] = mem[getAddr(pc)]
- reg['h'] = mem[hexStr(eval(getAddr(pc)) + 1,4)]
- pc.next(2)
- elif 'shld' in operation:
- mem[getAddr(pc)] = reg['l']
- mem[hexStr(eval(getAddr(pc)) + 1,4)] = reg['h']
- elif 'ldax' in operation:
- addr = '0x' + hexStr(reg[operation[-1]]) + hexStr(reg[regPairs[operation[-1]]])
- reg['a'] = mem[addr]
- elif 'stax' in operation:
- addr = '0x' + hexSrt(reg[operation[-1]]) + hexStr(reg[regPairs[operation[-1]]])
- mem[addr] = reg['a']
- elif 'xchg' in operation:
- reg['h'],reg['l'],reg['d'],reg['e'] = reg['d'],reg['e'],reg['h'],reg['l']
- elif 'add' in operation or 'adc' in operation:
- add(operation[-1],1 if 'adc' in operation else 0)
- elif 'adi' in operation or 'aci' in operation:
- pc.next()
- add(mem[pc()],1 if 'aci' in operation else 0)
- elif 'sub' in operation or 'sbb' in operation:
- sub(operation[-1],1 if 'sbb' in operation else 0)
- elif 'sui' in operation or 'sbi' in operation:
- pc.next()
- sub(mem[pc()],1 if 'sbi' in operation else 0)
- elif 'inr' in operation or 'dcr' in operation:
- carry = flags['cy']
- if operation[-1] != 'm':
- add(1,0,operation[-1])
- elif operation[-1] == 'm':
- mem[hexStr(reg['h']) + hexStr(reg['l'])] += 1
- else:pass
- flags['cy'] = carry
- elif 'dcr' in operation:
- carry = flags['cy']
- if operation[-1] != 'm':
- sub(1,0,operation[-1])
- elif operation[-1] == 'm':
- mem[hexStr(reg['h']) + hexStr(reg['l'])] -=1
- else:pass
- elif 'inx' in operation or 'dcx' in operation:
- pair = '0x' + hexStr(reg[operation[-1]]) + hexStr(reg[regPairs[operation[-1]]])
- pair = hexStr(eval(pair) + (1 if 'inx' in operation else -1))
- reg[operation[-1]],reg[regPairs[operation[-1]]] = eval('0x' + pair[:2]),eval('0x' + pair[2:])
- elif 'dad' in operation:
- reg['l'] += reg[regPairs[operation[-1]]]
- if reg['l'] >= 256:
- reg['l'] = hexStr(reg['l'])[-2:]
- flags['cy']= 1
- reg['h'] = reg[operation[-1]] + flags['cy']
- if reg['h'] >= 256:
- reg['h'] = hexStr(reg['h'])[-2:]
- flags['cy'] = 1
- elif 'daa' in operation:
- if (flags['ac'] == 1) or not((hexStr(reg['a'])[-1]).isalpha()):reg['a'] += 0x6
- if (flags['cy'] == 1) or not((hexStr(reg['a']).zfill(4))[:2]).isaplha(): reg['a'] += 0x60
- flagUpdate()
- elif 'jmp' in operation:
- pc.address = '0x' + hexStr(eval(getAddr(pc)) - 1,4)
- elif True in jump:
- conditions = [bool(flags['z']),not bool(flags['z']),bool(flags['cy']),not bool(flags['cy']),\
- bool(flags['p']),not bool(flags['p']),bool(flags['s']) ,not bool(flags['s'])]
- if conditions[jump.index(True)]:
- pc.address = '0x' + hexStr(eval(getAddr(pc)) - 1,4)
- else:
- pc.next(2)
- elif 'pchl' in operation:
- pc.address = '0x' + hexStr(reg['h']).zfill(2) + hexStr(reg['l']).zfill(2)
- pc.address = '0x' + hexStr(pc.value() - 1,4)
- elif 'ana' in operation:
- bit(0, (operation[-1] if 'ana' in operation else mem[hexStr(pc.value() + 1,4)]))
- flagUpdate('szp')
- flags['cy'], flags['ac'] = 0, 1
- elif 'ora' in operation or 'ori' in operation:
- bit(1, (operation[-1] if 'ora' in operation else mem[hexStr(pc.value() + 1,4)]))
- flagUpdate('szp')
- flags['cy'], flags['ac'] = 0, 0
- elif 'xra' in operation or 'xri' in operation:
- bit(2, (operation[-1] if 'xra' in operation else mem[hexStr(pc.value() + 1,4)]))
- flagUpdate('szp')
- flags['cy'], flags['ac'] = 0, 0
- elif 'stc' in operation:
- flags['cy'] = 1
- elif 'cma' in operation:
- reg['a'] = negate(reg['a'])
- elif 'cmc' in operation:
- flags['cy'] = int(not flags['cy'])
- elif 'rar' in operation or 'ral' in operation:
- byte = str(flags['cy'])*(operation[-1] == 'r') + bin(reg['a']).replace('0b','').zfill(8) + str(flags['cy'])*(operation[-1] == 'l')
- if 'rar' in operation:
- reg['a'] = eval('0b' + byte[:-1])
- flags['cy'] = eval('0b' + byte[-1])
- else:
- reg['a'] = eval('0b' + byte[1:])
- flags['cy'] = eval('0b' + byte[0])
- pc.next()
- #-------------------------------------------------------------------------------
- #============================= Interface Functions =============================
- def drawButtons():
- global buttons, buttonFrame
- numPadText = ['C\nU1','D\nU2','E\nU3','F\nU4',\
- '8\nGo/H','9\nL','A\nLOAD','B\nSAVE',\
- '4\nSPH','5\nSPL','6\nPCH','7\nPCL',\
- '0\nSET','1\nCODE','2\nSTEP','3\nREG']
- opPadText = "VI,DCR,EXEC,INR".split(',')
- gap = 50
- startX, startY = 350, 0
- width, height = 100, 100
- for i in range(4):
- buttons.append(Button(buttonFrame, opPadText[i],
- startX - width - gap,
- startY + (height*i),
- width, height, buttonPress))
- for i in range(4):
- for j in range(4):
- buttons.append(Button(buttonFrame, numPadText[4*i+j],
- startX + (width*j),
- startY + (height*i),
- width, height, buttonPress))
- buttons.append(Button(buttonFrame, "RST",
- startX - (width*2) - gap, startY,
- width-2, height-2, buttonPress))
- def update():
- global addressLED, contentLED, address, content
- for i, char in enumerate(address.replace('0x','')):
- addressLED[i].colorSeg(char)
- for i, char in enumerate(content):
- contentLED[i].colorSeg(char)
- def buttonPress(key):
- global address, content, activeField, mode, mem
- # print "You pressed {}\nMode: {}\nActive:{}".format(key, mode, activeField)
- if len(key) < 2 and ('0' <= key <= 'f'): # pressed key is a digt/numpad key
- if mode == "reset":
- # if 'reset' mode then keys have special meaning
- # denoted by text blow the numbers on the keys
- if key == "0": # '0' means 'SET' instruction
- activeField = "address"
- #firstEntry = True # the first entry would blank the address
- address, content = ' '*4, ' '*2
- mode = "entry"
- elif key == "3": # '3' means 'REG' instruction
- mode = "reg"
- activeField = "address"
- address, content = ' '*4, ' '*2
- update()
- elif key == "8": # '8' means 'GO' instruction
- address, content = ' '*4, ' '*2
- mode = "go"
- activeField = "address"
- update()
- elif mode in ["entry","go"]:
- # if 'entry' mode, the numbers are appended to
- # the respective field denoted by activeField variable
- if activeField == "content":
- content = (content + key)[1:] # append key to current value
- elif activeField == "address":
- '''if firstEntry: # if it is first entry clear the earlier value
- address = ' '*3 + key
- firstEntry = False
- else:'''
- address = (address + key)[1:] # append key to current value
- update()
- elif mode == "reg":
- if key == "rst":
- mode = "reset"
- address, content = 'frie', 'nd'
- elif key in 'abcde':
- address = ' '*3 + key
- content = hexStr(reg[key], 2)
- elif key == "8":
- address = ' '*3 + 'h'
- content = hexStr(reg['h'], 2)
- elif key == '9':
- address = ' '*3 + 'l'
- content = hexStr(reg['l'], 2)
- elif key == 'f':
- address = ' '*3 + 'f'
- content = hexStr(eval('0b' + ''.join([str(flags[char]) for char
- in 's,z,-,ac,-,p,-,cy'.split(',')])), 2)
- update()
- elif key == "inr": # pressed 'INR' key
- if activeField == "address":
- if mode == "reg":
- address = ' '*3 + ('abcdehlf'[('abcdehlf'.index(address[-1])+1)%8])
- content = hexStr(reg[address[-1]], 2)
- else:
- activeField = "content"
- if mem.has_key(address):
- content = hexStr(mem[address], 2)
- else:
- content, mem[address] = '00', 0
- elif activeField == "content":
- try:
- mem[address] = int(content, 16)
- except ValueError:
- address, content = 'ferr', 'or'
- else:
- address = hexStr(int(address,16) + 1, 4)
- if mem.has_key(address):
- content = hexStr(mem[address], 2)
- else:
- content, mem[address] = '00', 0
- update()
- elif key == 'rst': # pressed 'RST' key
- address, content = "frie", "nd"
- mode = "reset"
- update()
- elif key == "dcr": # pressed 'DCR' key
- if activeField == "address":
- if mode == "reg":
- address = ' '*3 + ('abcdehlf'[('abcdehlf'.index(address[-1])-1)%8])
- content = hexStr(reg[address[-1]], 2)
- else:
- activeField = "content"
- if mem.has_key(address):
- content = hexStr(mem[address], 2)
- else:
- content, mem[address] = '00', 0
- elif activeField == "content":
- mem[address] = int(content, 16)
- address = hexStr(int(address,16) - 1,4)
- if mem.has_key(address):
- content = hexStr(mem[address], 2)
- else:
- if address == 'bfff':
- win32api.MessageBox(0, "You cannot edit memory below C000.",
- "Warning")
- address = 'c000'
- content = hexStr(mem[address], 2)
- else:
- content, mem[address] = '00', 0
- update()
- elif key == "exec":
- if mode == "go":
- activeField = ""
- print "Executing from {}".format(address)
- try:
- execute(address)
- except BaseException as e:
- address, content = 'ferr', 'or'
- update()
- print "\n\n",e.message
- else:
- buttonPress('rst')
- #-------------------------------------------------------------------------------
- #=============================== User Interface ================================
- root = Tk()
- root.title('8085 Microprocessor simulator')
- screenHeight, screenWidth = root.winfo_screenheight(), root.winfo_screenwidth()
- windowHeight, windowWidth = int(screenHeight*(5/6.0)), int(screenWidth*(2/3.0))
- windowPadX, windowPadY = int(screenWidth*(1/6.0)), int(screenHeight*(1/24.0))
- root.geometry('{}x{}+{}+{}'.format(windowWidth, windowHeight, windowPadX, windowPadY))
- root.pack_propagate(False)
- root.config(background = 'black')
- #..................................Key Bindings.................................
- def f(e):
- char = e.char
- if char in '0123456789abcdef':
- buttonPress(e.char)
- elif char == '+':
- buttonPress('inr')
- elif char == '-':
- buttonPress('dcr')
- for char in '0123456789+-abcdef':
- root.bind(char, f)
- root.bind('<space>', lambda e:buttonPress('rst'))
- root.bind('<Return>', lambda e:buttonPress('exec'))
- #...............................................................................
- displayFrame = Frame(root, background = 'black', height=200)
- displayFrame.pack(side=TOP, fill=X)
- buttonFrame = Frame(root, background = 'black')
- buttonFrame.pack(side=TOP, fill=BOTH, expand=1)
- #b1 = Button(buttonFrame, "RST", 50, 50, 75, 75, buttonPress)
- addressLED = [LED(displayFrame, str(i), 75*i + 200, 25, 75, 150) for i in range(4)]
- contentLED = [LED(displayFrame, str(i), 75*i + (200+75*4+25), 25, 75, 150) for i in range(2)]
- address = ""
- content = ""
- activeField = ""
- firstEntry = False
- mode = 'reset'
- buttons = []
- drawButtons()
- #-------------------------------------------------------------------------------
- #============================ Functionality Checks =============================
- address = "frie"
- content = "nd"
- update()
- root.mainloop()
- def main():
- pass
- if __name__ == '__main__':
- main()
- #-------------------------------------------------------------------------------
- # Note:
- # Redundant lines: 129-132, 142-145 and 154-163
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement