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: 2.0.1
- # Created: 31/01/2013
- # Copyright: (c) 2013 Cubes and Codes
- # 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 * # provides base for GUI
- import tkFileDialog, tkMessageBox
- import re, pickle, os, sys # regex, file saving/loading, system path
- from time import time
- from led import LED # module for LED displays
- #-------------------------------------------------------------------------------
- #============================ Opcode initialization ============================
- opcode = {} # empty <dict> to store Hex codes and corresponding MatchObjects
- # regex to capture data from file (format specified below)
- template = re.compile(
- """
- \d+\. # Serial Number
- \ ([A-Z]+) # Instruction
- \ ?([\w-]*),? # First Operand (optional)
- \ ?([\w]*) # Second Operand (optional)
- \ ([A-Z0-9]{2}) # Hex Code
- """, re.VERBOSE)
- # Open file 'opcode.txt' containing all the Opcodes in the following format
- #
- # <Sr.no.>. <Opcode> <Operand1>, <Operand2> <Hex Code> <Number of bytes>
- #
- # Examples:
- # 1. ACI Data CE 2
- # 16. ADD L 85 1
- # 30. CM Label FC 3
- # 31. CMA 2F 1
- # 40. MOV C, L 4D 1
- with open(os.path.join(os.getcwd(), r'bin\opcode.txt'), 'r') as f:
- for line in f:
- mo = template.search(line)
- # group(4) of MatchObject conains Hex Code which will act as keys
- opcode[int(mo.group(4),16)] = mo
- #-------------------------------------------------------------------------------
- #============================ Memory and Registers =============================
- reg = {'a':0,'b':0,'c':0,'d':0,'e':0, 'h':0,'l':0,'m':0} # registers
- mem = {} # Memory/RAM
- flags = {'s':0,'z':0,'ac':0,'p':0,'cy':0,'-':0} # flag registers
- regPairs = {'h':'l','b':'c','d':'e'} # registry *pairs*
- stackPointer = 0xf000
- programCounter = 0x0000
- #-------------------------------------------------------------------------------
- #============================== General Functions ==============================
- def hexStr(n, fill=2):
- """Return hexadecimal representation of 'n' as a string without
- '0x' in the beginning and padded with zeroes to form
- 'fill' number of characters"""
- return hex(n).replace('0x','').zfill(fill)
- def binStr(n, fill=8):
- """Return binary representation of 'n' as a string without
- '0b' in the beginning and padded with zeroes to form
- 'fill' number of characters"""
- return bin(n).replace('0b','').zfill(fill)
- #-------------------------------------------------------------------------------
- #============================== Class Definitons ===============================
- class button:
- """Class for managing onscreen buttons, their creation and
- their key bindings"""
- text = "" # Main text to be displayed on the button face
- subText = "" # Sub-text displayed below main-text
- key = "" # Key to be passed to binded function for identification
- master = None # Parent widget
- canvas = None # main canvas
- def __init__(self, master, buttonText, locX, locY, width, height, clickFunc):
- """Initialize button and draw it onto 'master'.
- Parameters:
- | master: parent Tkinter widget
- | buttonText: text to be displayed on button face
- | interprets newline character as delimiter
- | for main text and sub-text
- | locX, locY: x and y coordinates of top-left corner of button
- | width, height: dimensions of button
- | clickFunc: Function to which mouse-click event will be binded.
- | This function will be passes 'key' as an identification
- | of which button was clicked.
- """
- self.canvas = Canvas(master, background='#3C3C3C',
- height=height, width=width,
- highlightthickness=2, highlightbackground='black',
- 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') # separate main text and sub-text
- 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 circle:
- """
- Creates a canvas with a circle in it. Circle
- color can be changed by simply calling it
- along with a value denoting on or off.
- """
- def __init__(self, master, locX, locY, width, height):
- self.canvas = Canvas(master, height=height, width=width, bg='black',
- highlightthickness=0)
- self.canvas.place(x=locX,y=locY)
- self.canvas.create_oval([3,3,width,height], fill='#200000', tag='dot')
- def __call__(self, n):
- if n:
- self.canvas.itemconfig('dot', fill = '#FF0000')
- else:
- self.canvas.itemconfig('dot', fill = '#200000')
- class counter:
- """Class to provide basic Program Counter(PC) functionality."""
- address = "" # address to which counter points
- def __init__(self, address):
- """Initialize counter based on address supplied as a hexadecimal
- number string"""
- self.address = address.replace('0x','')
- def next(self, increment = 1):
- """Increment address by 'increment' to point to proceeding
- address locations."""
- self.address = hexStr(int(self.address,16) + increment, 4)
- # print self.address #for debugging
- def __call__(self):
- """Return current address as a hexadecimal string(without '0x')
- on being called. This allows convenient usage of counter."""
- return self.address
- def value(self):
- """Return integer value of hexadecimal address to which it points"""
- return int(self.address,16)
- #-------------------------------------------------------------------------------
- #======================== Execution assisting functions ========================
- def flagUpdate(affect = 'szpcy',register = 'a'):
- """Updates required flags as specified in 'affect'
- according to 'register' content in <dict> 'reg'
- (cannot handle auxiliary carry flag hence this task is
- assigned to 'add' function.)"""
- global reg,flags
- acc = reg[register]
- if (('cy' in affect) and (acc >= 256)):
- flags['cy'] = 1
- reg[register] = int(binStr(acc)[-8:],2)
- acc = reg[register]
- else:
- flags['cy'] = 0
- if 's' in affect:
- flags['s'] = int(binStr(acc)[0])
- if 'z' in affect:
- flags['z'] = int(acc == 0)
- if 'p' in affect:
- flags['p'] = int(not binStr(acc).count('1')%2)
- def negate(number, fill=8):
- """Return integer value of 1's complement of number considering
- it as a 'fill' bit number"""
- number = binStr(number, fill)
- number = number.replace('1','*1').replace('0','1').replace('*1','0')
- return int(number,2)
- def move(rd,rs):
- """Implementation of following instructions
- MOV rd/M, rs/M
- MVI rd, 8-bit Data
- LXI rp
- LDA 16-bit Address
- """
- global mem,reg
- if rd in reg and rs in reg: # register/M to register/M
- if (rd == 'm') ^ (rs =='m'):
- # XOR to make sure both 'rd','rs' are not 'm'
- # in which case do nothing
- if rd =='m':
- mem[hexStr(reg['h'])+hexStr(reg['l'])] = reg[rs]
- else:
- reg[rd] = mem[hexStr(reg['h'])+hexStr(reg['l'])]
- # only both 'm' and both not 'm' cases fall through
- elif rd != 'm': # confirms none of 'rd', 'rs' is 'm'
- reg[rd] = reg[rs]
- else: # content to register(eg. MVI)
- reg[rd] = rs
- def add(operand,cy,operated = 'a'):
- """Primary implementation of following instructions
- ADD r/M
- ADC r/M
- ADI 8-bit Data
- ACI 8-bit Data
- Also provides assistance for 'sub' function
- and following instructions
- INR r/M
- DCR r/M
- DAD rp
- DAA
- Adds operand to register 'operated' and handles
- the auxiliary carry flag. 'cy' specifies whether carry is to be added
- depending on value of cy(0->without,1->with). Result is in accumulator"""
- global mem,reg,flags
- if operand == 'm':
- operand = mem[hexStr(reg['h']) + hexStr(reg['l'])]
- elif operand in reg:
- operand = reg[operand]
- if operated == 'm':
- reg['m'] = mem[hexStr(reg['h']) + hexStr(reg['l'])]
- if (((reg[operated] % 16) + (operand % 16)) >= 16):
- flags['ac'] = 1
- else:
- flags['ac'] = 0
- reg[operated] = reg[operated] + operand + cy*flags['cy']
- if operated == 'm':
- mem[hexStr(reg['h']) + hexStr(reg['l'])] = reg['m']
- def sub(operand,borrow,operated = 'a'):
- """Implementation of following instructions
- SUB r
- SBB r
- SUI r
- SBI r
- Indirectly carries out addition. 'borrow' determines if
- carry flag is to be considered available for borrowing
- while subtracting."""
- if operand == 'm':
- operand = mem[hexStr(reg['h']) + hexStr(reg['l'])]
- if operand in reg:
- operand = reg[operand]
- operand = negate(operand) + 1
- operated = borrow*flags['cy']*256 + reg[operated]
- add(operand,borrow,operated)
- flagUpdate('cy')
- flags['cy'] = int(not(flags['cy']))
- def bit(operation,rs):
- """Returns bitwise operation result of accumulator and register or data
- 'oper' can be:
- 0: bit-wise 'and'
- 1: bit-wise 'or'
- 2: bit-wise 'xor'"""
- global reg,flags
- # List of operations AND, OR, XOR in order
- operlist = [lambda x,y:x&y, lambda x,y:x|y, lambda x,y:x^y]
- if rs in reg:
- if rs == 'm': # ANA M, ORA M, XRA M
- rs = mem[hexStr(reg['h'])+hexStr(reg['l'])]
- bit(operation,rs)
- else: # ANA r, ORA r, XRA r
- reg['a'] = operlist[operation](reg['a'],reg[rs])
- else: # ANI, ORI, XRI
- reg['a'] = operlist[operation](reg['a'],rs)
- def getFlags():
- """Combines flag-bits to form a return a single
- 8-bit hexadecimal number string(without '0x').
- Format: s z - ac - p - cy"""
- global flags
- s = ''.join([str(flags[char]) for char in flagList])
- return hexStr(int(s,2), 2)
- def setFlags(n):
- """Sets flag-bits to individual bit obtained from
- converting given number to binary.
- Format: s z - ac - p cy"""
- global flags
- s = binStr(n,8)
- for i,char in enumerate(flagList):
- flags[char] = int(s[i])
- flags['-'] = 0
- def shift(direction, num, fill):
- """Shifts 'num' in given 'direction' bit-wise after
- padding it with zeroes till 'fill' number of characters"""
- byte = binStr(num, fill)
- if direction == 'r':
- byte = byte[-1] + byte[:-1]
- elif direction == 'l':
- byte = byte[1:] + byte[0]
- return int(byte,2)
- #============================= Executing function ==============================
- def execute(start):
- """Function to execute program stored in global variable
- 'mem' starting from memory location given by 'start' as
- a hexadecimal string.
- Forms the core of this application. It basically is a long
- if-elif clause converting each memory location hexadecimal
- content to the corresponding instruction using global variable
- 'opcode' which contains instructions fetched from file
- 'opcode.txt' as Regex MatchObjects.
- Instructions not yet implemented:
- (and probably won't ever be implemented)
- IN port
- OUT port
- EI
- DI
- RIM
- SIM"""
- global mem, reg, flags, regPairs, programCounter, stackPointer, instrCount
- pc = counter(start) # initialize counter from 'start' address
- timeSlice, t = 15, time()
- running = True
- instrCount = 0
- def getAddr(startFrom):
- """Extract 4 byte address from address locations proceeding given
- 'startFrom' location in the memory, lsb then msb"""
- return (hexStr(mem[hexStr(startFrom.value() + 2, 4)]) +
- hexStr(mem[hexStr(startFrom.value() + 1, 4)]))
- flaggers =['z', 'nz', 'c', 'nc', 'pe', 'po', 'm', 'p']
- jumpers = [ 'jmp']+['j' + i for i in flaggers]
- callers = ['call']+['c' + i for i in flaggers]
- returns = [ 'ret']+['r' + i for i in flaggers]
- while running and (time()-t <= timeSlice):
- instruction, op1, op2 = [opcode[mem[pc()]].group(i).lower() for i in [1,2,3]]
- print instruction, op1, op2
- instrCount += 1
- if instruction == 'mov':
- move(op1,op2)
- elif instruction == 'mvi':
- pc.next()
- move(op1,mem[pc()])
- elif instruction == 'lxi':
- pc.next()
- move(regPairs[op1],mem[pc()])
- pc.next()
- move(op1,mem[pc()])
- elif instruction == 'ldax':
- addr = hexStr(reg[op1]) + hexStr(reg[regPairs[op1]])
- reg['a'] = mem[addr]
- elif instruction == 'stax':
- addr = hexStr(reg[op1]) + hexStr(reg[regPairs[op1]])
- mem[addr] = reg['a']
- elif instruction == 'lda':
- move('a', mem[getAddr(pc)])
- pc.next(2)
- elif instruction == 'sta':
- mem[getAddr(pc)] = reg['a']
- pc.next(2)
- elif instruction == 'lhld':
- reg['l'] = mem[getAddr(pc)]
- reg['h'] = mem[hexStr(int(getAddr(pc),16) + 1,4)]
- pc.next(2)
- elif instruction == 'shld':
- mem[getAddr(pc)] = reg['l']
- mem[hexStr(int(getAddr(pc),16) + 1,4)] = reg['h']
- elif instruction == 'xchg':
- reg['h'],reg['l'],reg['d'],reg['e'] = reg['d'],reg['e'],reg['h'],reg['l']
- elif instruction in ['add','adc']:
- add(op1, instruction=='adc')
- flagUpdate()
- elif instruction in ['adi','aci']:
- pc.next()
- add(mem[pc()],instruction=='aci')
- flagUpdate()
- elif instruction in ['sub','sbb']:
- sub(op1,instruction=='sbb')
- flagUpdate('szp')
- elif instruction in ['sui','sbi']:
- pc.next()
- sub(mem[pc()],instruction=='sbi')
- flagUpdate('szp')
- elif instruction == 'inr':
- add(1, 0, op1)
- carry = flags['cy']
- flagUpdate('szpcy',op1)
- flags['cy'] = carry
- elif instruction == 'dcr':
- add(0xff, 0, op1)
- carry = flags['cy']
- flagUpdate('szpcy',op1)
- flags['cy'] = carry
- elif instruction in ['inx','dcx']:
- pair = hexStr(reg[op1]) + hexStr(reg[regPairs[op1]])
- pair = hexStr(int(pair,16) + [1,-1][instruction=='dcx'])
- reg[op1],reg[regPairs[op1]] = int(pair[:2],16),int(pair[2:],16)
- elif instruction == 'dad':
- reg['l'] += reg[regPairs[op1]]
- if reg['l'] >= 256:
- reg['l'] = int(bin(reg['l'])[-8:],2)
- add(1,0,'h')
- flagUpdate('cy','h')
- reg['h'] += reg[op1]
- flagUpdate('cy','h')
- elif instruction == 'daa':
- if flags['ac'] or ((hexStr(reg['a']))[-1]).isalpha():
- add(6, 0)
- if flags['cy'] or ((hexStr(reg['a']))[0]).isalpha():
- add(0x60, 0)
- flagUpdate()
- elif instruction == 'jmp':
- pc.address = hexStr(int(getAddr(pc),16) - 1,4)
- elif instruction in jumpers + callers + returns:
- conditions = [True,\
- 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 instruction in jumpers:
- if conditions[jumpers.index(instruction)]:
- pc.address = hexStr(int(getAddr(pc),16)-1, 4)
- else:
- pc.next(2)
- elif instruction in callers:
- if conditions[callers.index(instruction)]:
- mem[hexStr(stackPointer - 1, 4)] = pc.value()/0x100
- mem[hexStr(stackPointer - 2, 4)] = pc.value()%0x100
- stackPointer -= 2
- pc.address = hexStr(getAddr(pc)-1, 4)
- else:
- pc.next(2)
- elif instruction in returns:
- if conditions[returns.index(instruction)]:
- pc.address = hexStr(mem[hexStr(stackPointer,4)])+ \
- hexStr(mem[hexStr(stackPointer + 1)] - 1)
- stackPointer += 2
- else:
- pc.next(2)
- elif instruction == 'pchl':
- pc.address = hexStr(reg['h'], 2) + hexStr(reg['l'], 2)
- pc.address = hexStr(pc.value() - 1,4)
- elif instruction == 'xthl':
- reg['l'], mem[hexStr(stackPointer,4)] = mem[hexStr(stackPointer,4)], reg['l']
- reg['h'], mem[hexStr(stackPointer+1,4)] = mem[hexStr(stackPointer+1,4)], reg['h']
- elif instruction == 'sphl':
- stackPointer = int(hexStr(reg['h']) + hexStr(reg['l']), 16)
- elif instruction == 'push':
- if op1 == 'psw':
- mem[hexStr(stackPointer-1, 4)] = reg['a']
- mem[hexStr(stackPointer-2, 4)] = int(getFlags(),16)
- else:
- mem[hexStr(stackPointer-1, 4)] = reg[op1]
- mem[hexStr(stackPointer-2, 4)] = reg[regPairs[op1]]
- stackPointer -= 2
- elif instruction == 'pop':
- if op1 == 'psw':
- setFlags(mem[hexStr(stackPointer, 4)])
- reg['a'] = mem[hexStr(stackPointer+1, 4)]
- else:
- reg[regPairs[op1]] = mem[hexStr(stackPointer, 4)]
- reg[op1] = mem[hexStr(stackPointer+1, 4)]
- stackPointer += 2
- elif instruction in ['ana','ani']:
- bit(0, ([op1,mem[hexStr(pc.value() + 1,4)]][instruction=='ani']))
- flagUpdate('szp')
- flags['cy'], flags['ac'] = 0, 1
- elif instruction in ['ora','ori']:
- bit(1, ([op1,mem[hexStr(pc.value() + 1,4)]][instruction=='ori']))
- flagUpdate('szp')
- flags['cy'], flags['ac'] = 0, 0
- elif instruction in ['xra','xri']:
- bit(2, ([op1,mem[hexStr(pc.value() + 1,4)]][instruction=='xri']))
- flagUpdate('szp')
- flags['cy'], flags['ac'] = 0, 0
- elif instruction == 'cmp':
- if op1 == 'm':
- m = mem[hexStr(reg['h'])+hexStr(reg['l'])]
- flags['cy'] = int(reg['a'] < m)
- flags['z'] = int(reg['a'] == m)
- else:
- flags['cy'] = int(reg['a'] < reg[op1])
- flags['z'] = int(reg['a'] == reg[op1])
- elif instruction == 'cpi':
- op1 = mem[hexStr(pc.value() + 1, 4)]
- flags['cy'] = int(reg['a'] < op1)
- flags['z'] = int(reg['a'] == op1)
- elif instruction == 'rlc':
- reg['a'] = shift('l', reg['a'], 8)
- flags['cy'] = binStr(reg['a'])[-1]
- elif instruction == 'rrc':
- reg['a'] = shift('r', reg['a'], 8)
- flags['cy'] = binStr(reg['a'])[0]
- elif instruction == 'ral':
- reg['a'] = shift('l', reg['a'], 8)
- carry, flags['cy'] = flags['cy'], int(binStr(reg['a'])[-1])
- reg['a'] = int(binStr(reg['a'],2)[:-1] + str(carry))
- elif instruction == 'rar':
- reg['a'] = shift('r', reg['a'], 8)
- carry, flags['cy'] = flags['cy'], int(binStr(reg['a'])[0])
- reg['a'] = int(str(carry) + binStr(reg['a'])[1:], 2)
- elif instruction == 'cma':
- reg['a'] = negate(reg['a'])
- elif instruction == 'cmc':
- flags['cy'] = int(not flags['cy'])
- elif instruction == 'stc':
- flags['cy'] = 1
- elif instruction in ['rst','hlt']:
- running = False
- programCounter = pc.value()
- pc.next()
- programCounter = pc.value() + 1
- #-------------------------------------------------------------------------------
- #============================= 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(add=None):
- global addressLED, contentLED, addDot, conDot, address, content, mem
- if not add:
- for i in range(4):
- addressLED[i].colorSeg(address[len(address)-4+i])
- for i in range(2):
- contentLED[i].colorSeg(content[len(content)-2+i])
- addDot(activeField=='address')
- conDot(activeField=='content')
- else:
- if mem.has_key(add):
- content = hexStr(mem[add])
- else:
- content, mem[add] = '00', 0
- update()
- def showHelp(e):
- helpText = """
- Press F1 to view help... You probably already know that.
- Key-mapping:
- -----------
- =>Keys "0" through "9"(normal or number-pad) mean "0" through
- '9' on the on-screen numpad.
- =>"Space-bar" translates to the "RST" key
- =>Keys "+" and "-" stand for "INR" and "DCR" keys respectively
- =>"Enter" or "Return" key means "EXEC"
- The "VI" key is just for realism, and does nothing but sit
- and change it's color on being awakened by the pointy white
- arrow you manipulate using a device which resembles a nasty
- rodent.
- Made by
- -Aditya Sriram
- (a.k.a P.R.Vaidyanathan)
- """
- tkMessageBox.askokcancel("Help", helpText)
- def buttonPress(key):
- global address, content, activeField, mode, mem, regList, regKeys, regCount
- global stackPointer, programCounter, flagList
- 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"
- elif key == "b": # 'B' means 'SAVE' instruction
- root.iconify()
- root.update()
- f = tkFileDialog.asksaveasfile(mode = "w",
- initialdir = os.path.join(os.getcwd(), "bin"),
- defaultextension = '.dam',
- filetypes = [("Data Assisting Microprocessor", '.dam')])
- if f:
- pickle.dump((mem, stackPointer), f)
- print "Saved successfully"
- f.close()
- else:
- tkMessageBox.askokcancel("File Not Saved",
- "The file could not be saved.\nPress the \
- 'SAVE' button to try saving again.")
- root.deiconify()
- elif key == "a": # 'A' means 'LOAD' instruction
- root.iconify()
- root.update()
- #fname = raw_input("Enter the name of the file to be loaded\n")
- f = tkFileDialog.askopenfile(mode = "r",
- initialdir = os.path.join(os.getcwd(),"bin"),
- filetypes = [('Data Assisting Microprocessor', '.dam')])
- try:
- temp = pickle.load(f)
- if isinstance(temp, dict):
- mem = temp
- elif isinstance(temp, tuple):
- mem, stackPointer = temp
- except AttributeError:
- tkMessageBox.askokcancel("No File Selected",
- "You have not selected any file so no file was \
- loaded.\n Press 'LOAD' again if you want to load a file")
- else:
- print "Loaded successfully"
- f.close()
- root.deiconify()
- root.update()
- 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":
- address = (address + key)[1:] # append key to current value
- update()
- elif mode == "reg":
- if key == "rst":
- mode = "reset"
- address, content = 'frie', 'nd'
- activeField = ""
- elif activeField == "address":
- if 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 = getFlags()
- elif key == '4':
- address = ' sph'
- content = hexStr(stackPointer/0x100)
- elif key == '5':
- address = ' spl'
- content = hexStr(stackPointer%0x100)
- elif key == '6':
- address = ' pch'
- content = hexStr(programCounter/0x100)
- elif key == '7':
- address = ' pcl'
- content = hexStr(programCounter%0x100)
- regCount = regKeys.index(key)
- activeField = "content"
- elif activeField == "content":
- content = (content + key)[1:]
- update()
- elif key in ["inr","dcr"]: # pressed 'INR' key
- diff = 1 if key == "inr" else -1
- if activeField == "address":
- activeField = "content"
- update(address)
- elif activeField == "content":
- if mode == "reg":
- if regList[regCount] in reg.keys():
- reg[regList[regCount]] = int(content,16)
- else:
- if regList[regCount] == 'f':
- setFlags(int(content, 16))
- elif regList[regCount] == 'sph':
- stackPointer = int(content + hexStr(stackPointer%0x100),16)
- elif regList[regCount] == 'spl':
- stackPointer = int(hexStr(stackPointer/0x100) + content,16)
- elif regList[regCount] == 'pch':
- programCounter = int(content + hexStr(programCounter%0x100),16)
- elif regList[regCount] == 'pcl':
- programCounter = int(hexStr(programCounter/0x100) + content,16)
- activeField = "address"
- regCount = (regCount + diff)%12
- buttonPress(regKeys[regCount])
- else:
- try:
- mem[address] = int(content, 16)
- except ValueError:
- address, content = 'ferr', 'or'
- update()
- else:
- address = hexStr(int(address,16) + diff, 4)
- update(address)
- elif key == 'rst': # pressed 'RST' key
- address, content = "frie", "nd"
- mode = "reset"
- activeField = ""
- update()
- elif key == "exec":
- if mode == "go":
- activeField = ""
- pc = address
- print "Executing from {}".format(pc)
- address, content = ' e', ' '
- update()
- root.update()
- t = time()
- try:
- execute(pc)
- except:
- address, content = 'ferr', 'or'
- update()
- print "\nUnexpected Error: ", sys.exc_info()
- else:
- print "Time taken: {}".format(time()-t)
- print "Instruction Count: {}".format(instrCount)
- 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')
- 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)
- #-------------------------------------------------------------------------------
- #================================ Key Bindings =================================
- def f(e):
- char = e.char
- if char == '+':
- buttonPress('inr')
- elif char == '-':
- buttonPress('dcr')
- else:
- buttonPress(e.char.lower())
- for char in '0123456789+-abcdefABCDEF':
- root.bind(char, f)
- root.bind('<space>', lambda e:buttonPress('rst'))
- root.bind('<Return>', lambda e:buttonPress('exec'))
- root.protocol("WM_DELETE_WINDOW", root.destroy)
- root.bind('<F1>', showHelp)
- #-------------------------------------------------------------------------------
- #========================= Interface Related Variables =========================
- addressLED = [LED(displayFrame, str(i), 75*i + 200, 25, 75, 150) for i in range(4)]
- addDot = circle(displayFrame, 505, 150, 15, 15)
- contentLED = [LED(displayFrame, str(i), 75*i + (200+75*4+25), 25, 75, 150) for i in range(2)]
- conDot = circle(displayFrame, 680, 150, 15, 15)
- address = "frie"
- content = "nd"
- activeField = ""
- firstEntry = False
- mode = 'reset'
- # chronological list of all registers, sp and pc and their keys
- regList = ['a','b','c','d','e','f','h','l','sph','spl','pch','pcl']
- regKeys = ['a','b','c','d','e','f','8','9', '4', '5', '6', '7']
- regCount = 0
- instrCount = 0
- flagList = ['s','z','-','ac','-','p','-','cy']
- buttons = []
- #-------------------------------------------------------------------------------
- #============================ Functionality Checks =============================
- update()
- def main():
- drawButtons()
- root.mainloop()
- if __name__ == '__main__':
- main()
- #-------------------------------------------------------------------------------
- # Todo3 Assembler
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement