Advertisement
AdityaSriram

up8085.py (v1.1)

Feb 7th, 2013
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 25.44 KB | None | 0 0
  1. #-------------------------------------------------------------------------------
  2. # Name:        up8085
  3. # Purpose:     Emulate the Dynalog microfriend 8085 microprocessor
  4. #
  5. # Author:      Aditya Sriram
  6. # Version:     1.1
  7. # Created:     31/01/2013
  8. # Copyright:   (c) 2013 Cubes and Codes
  9. # Licence:     GNU General Public License
  10. #
  11. # View <http://www.youtube.com/watch?v=k8kqdx--SLg> for a demonstration
  12. # of this program
  13. #-------------------------------------------------------------------------------
  14. #!/usr/bin/env python
  15.  
  16. #============================== External Modules ===============================
  17.  
  18. from Tkinter import *      # provides base for GUI
  19. import re, pickle, os, sys # regex, file saving/loading, system path
  20. from time import time,sleep
  21. from led import LED        # module for LED displays
  22.  
  23. #-------------------------------------------------------------------------------
  24. #============================ Opcode initialization ============================
  25.  
  26. opcode = {} # empty <dict> to store Hex codes and corresponding MatchObjects
  27.  
  28. # regex to capture data from file (format specified below)
  29. template = re.compile(
  30. """
  31. \d+\.              # Serial Number
  32. \ ([A-Z]+)         # Instruction
  33. \ ?([\w-]*),?      # First Operand (optional)
  34. \ ?([\w]*)         # Second Operand (optional)
  35. \ ([A-Z0-9]{2})    # Hex Code
  36. """, re.VERBOSE)
  37.  
  38. # Open file 'opcode.txt' containing all the Opcodes in the following format
  39. #
  40. # <Sr.no.>. <Opcode> <Operand1>, <Operand2> <Hex Code> <Number of bytes>
  41. #
  42. # Examples:
  43. # 1. ACI Data CE 2
  44. # 16. ADD L 85 1
  45. # 30. CM Label FC 3
  46. # 31. CMA 2F 1
  47. # 40. MOV C, L 4D 1
  48. with open(os.path.join(os.getcwd(), r'bin\opcode.txt'), 'r') as f:
  49.     for line in f:
  50.         mo = template.search(line)
  51.  
  52.     # group(4) of MatchObject conains Hex Code which will act as keys
  53.         opcode[int(mo.group(4),16)] = mo
  54.  
  55. #-------------------------------------------------------------------------------
  56. #============================ Memory and Registers =============================
  57.  
  58. reg = {'a':0,'b':0,'c':0,'d':0,'e':0,'f':0,'h':0,'l':0,'m':0} # registers
  59. mem = {}                                                      # Memory/RAM
  60. flags = {'s':0,'z':0,'ac':0,'p':0,'cy':0,'-':0}               # flag registers
  61. regPairs = {'h':'l','b':'c','d':'e'}                          # registry *pairs*
  62.  
  63. #-------------------------------------------------------------------------------
  64. #============================== General Functions ==============================
  65. def hexStr(n, fill=2):
  66.     """Return hexadecimal representation of 'n' as a string without
  67.    '0x' in the beginning and padded with zeroes to form
  68.    fill number of characters"""
  69.     return hex(n).replace('0x','').zfill(fill)
  70.  
  71. def binStr(n, fill=8):
  72.     """Return binary representation of 'n' as a string without
  73.    '0b' in the beginning and padded with zeroes to form
  74.    'fill' number of characters"""
  75.     return bin(n).replace('0b','').zfill(fill)
  76. #-------------------------------------------------------------------------------
  77. #============================== Class Definitons ===============================
  78.  
  79. class Button:
  80.     """Class for managing onscreen buttons, their creation and
  81.    their key bindings"""
  82.  
  83.     text = ""        # Main text to be displayed on the button face
  84.     subText = ""     # Sub-text displayed below main-text
  85.     key = ""         # Key to be passed to binded function for identification
  86.     master = None    # Parent widget
  87.     canvas = None    # main canvas
  88.  
  89.     def __init__(self, master, buttonText, locX, locY, width, height, clickFunc):
  90.         """Initialize button and draw it onto 'master'.
  91.        Parameters:
  92.         |  master: parent Tkinter widget
  93.         |  buttonText: text to be displayed on button face
  94.         |              interprets newline character as delimiter
  95.         |              for main text and sub-text
  96.         |  locX, locY: x and y coordinates of top-left corner of button
  97.         |  width, height: dimensions of button
  98.         |  clickFunc: Function to which mouse-click event will be binded.
  99.         |             This function will be passes 'key' as an identification
  100.         |             of which button was clicked.
  101.        """
  102.         self.canvas = Canvas(master, background='#3C3C3C',
  103.                              height=height, width=width, cursor="hand2")
  104.         self.canvas.place(x=locX, y=locY)
  105.         self.canvas.create_text(width/2, height/2,
  106.                                 font=("Monaco",min(height, width)/3-10),
  107.                                 text=buttonText, fill='white', justify=CENTER)
  108.  
  109.         buttonText = buttonText.split('\n') # separate main text and sub-text
  110.         self.text = buttonText[0]
  111.         if len(buttonText) > 1:
  112.             self.subText = buttonText[1]
  113.         self.key = self.text.lower()
  114.         self.master = master
  115.  
  116.         self.canvas.bind('<Enter>', lambda e: self.canvas.config(background='#222222'))
  117.         self.canvas.bind('<Leave>', lambda e: self.canvas.config(background='#3C3C3C'))
  118.         self.canvas.bind('<Button-1>', lambda e: clickFunc(self.key))
  119.  
  120.  
  121. class counter:
  122.     """Class to provide basic Program Counter(PC) functionality."""
  123.  
  124.     address = ""     # address to which counter points
  125.  
  126.     def __init__(self, address):
  127.         """Initialize counter based on address supplied as a hexadecimal
  128.        number string"""
  129.         self.address = address.replace('0x','')
  130.  
  131.     def next(self, increment = 1):
  132.         """Increment address by 'increment' to point to proceeding
  133.        address locations."""
  134.         self.address = hexStr(eval('0x' + self.address) + increment, 4)
  135.         # print self.address #for debugging
  136.  
  137.     def __call__(self):
  138.         """Return current address as a hexadecimal string(without '0x')
  139.        on being called. This allows convenient usage of counter."""
  140.         return self.address
  141.  
  142.     def value(self):
  143.         """Return integer value of hexadecimal address to which it points"""
  144.         return eval('0x' + self.address)
  145.  
  146. #-------------------------------------------------------------------------------
  147. #======================== Execution assisting functions ========================
  148. def flagUpdate(affect = 'szpcy',register = 'a'):
  149.     """Updates required flags as specified in 'affect'
  150.    according to 'register' content in <dict> 'reg'
  151.    (cannot handle auxiliary carry flag hence this task is
  152.    assigned to 'add' function.)"""
  153.     global reg,flags
  154.     acc = reg[register]
  155.     if (('cy' in affect) and (acc >= 256)):
  156.         flags['cy'] = 1
  157.         reg[register] = eval('0b' + binStr(acc)[-8:])
  158.         acc = reg[register]
  159.     else:
  160.         flags['cy'] = 0
  161.     if 's' in affect:
  162.         flags['s'] = int(binStr(acc)[0])
  163.     if 'z' in affect:
  164.         flags['z'] = int(acc == 0)
  165.     if 'p' in affect:
  166.         flags['p'] = int(not binStr(acc).count('1')%2)
  167.  
  168. def negate(number, fill=8):
  169.     """Return integer value of 1's complement of number considering
  170.    it as a 'fill' bit number"""
  171.     number = binStr(number, fill)
  172.     number = number.replace('1','*1').replace('0','1').replace('*1','0')
  173.     return eval('0b' + number)
  174.  
  175. def move(rd,rs):
  176.     """Implementation of following instructions
  177.    MOV rd/M, rs/M
  178.    MVI rd, 8-bit Data
  179.    LXI rp
  180.    LDA 16-bit Address
  181.    """
  182.     global mem,reg
  183.     if rd in reg and rs in reg:  # register/M to register/M
  184.         if (rd == 'm') ^ (rs =='m'):
  185.             # XOR to make sure both 'rd','rs' are not 'm'
  186.             # in which case do nothing
  187.             if rd =='m':
  188.                 mem[hexStr(reg['h'])+hexStr(reg['l'])] = reg[rs]
  189.             else:
  190.                 reg[rd] = mem[hexStr(reg['h'])+hexStr(reg['l'])]
  191.         # only both 'm' and both not 'm' cases fall through
  192.         elif rd != 'm':              # confirms none of 'rd', 'rs' is 'm'
  193.             reg[rd] = reg[rs]
  194.     else:                        # content to register(eg. MVI)
  195.         reg[rd] = rs
  196.  
  197. def add(operand,cy,operated = 'a'):
  198.     """Primary implementation of following instructions
  199.        ADD r/M
  200.        ADC r/M
  201.        ADI 8-bit Data
  202.        ACI 8-bit Data
  203.  
  204.    Also provides assistance for 'sub' function
  205.    and following instructions
  206.        INR r/M
  207.        DCR r/M
  208.        DAD rp
  209.        DAA
  210.  
  211.    Adds operand to register 'operated' and handles
  212.    the auxiliary carry flag. 'cy' specifies whether carry is to be added
  213.    depending on value of cy(0->without,1->with). Result is in accumulator"""
  214.     global mem,reg,flags
  215.     if operand == 'm':
  216.         operand = mem[hexStr(reg['h']) + hexStr(reg['l'])]
  217.     elif operand in reg:
  218.         operand = reg[operand]
  219.     if operated == 'm':
  220.         reg['m'] = mem[hexStr(reg['h']) + hexStr(reg['l'])]
  221.     if (((reg[operated] % 16) + (operand % 16)) >= 16):
  222.         flags['ac'] = 1
  223.     else:
  224.         flags['ac'] = 0
  225.     reg[operated] = reg[operated] + operand + cy*flags['cy']
  226.     if operated == 'm':
  227.         mem[hexStr(reg['h']) + hexStr(reg['l'])] = reg['m']
  228.  
  229. def sub(operand,borrow,operated = 'a'):
  230.     """Implementation of following instructions
  231.        SUB r
  232.        SBB r
  233.        SUI r
  234.        SBI r
  235.  
  236.    Indirectly carries out addition. 'borrow' determines if
  237.    carry flag is to be considered available for borrowing
  238.    while subtracting."""
  239.     if operand == 'm':
  240.         operand = mem[hexStr(reg['h']) + hexStr(reg['l'])]
  241.     if operand in reg:
  242.         operand = reg[operand]
  243.     operand = negate(operand) + 1
  244.     operated = borrow*flags['cy']*256 + reg[operated]
  245.     add(operand,borrow,operated)
  246.     flagUpdate('cy')
  247.     flags['cy'] = int(not(flags['cy']))
  248.  
  249. def bit(operation,rs):
  250.     """Returns bitwise operation result of accumulator and register or data
  251.    'oper' can be:
  252.    0: bit-wise 'and'
  253.    1: bit-wise 'or'
  254.    2: bit-wise 'xor'"""
  255.     global reg,flags
  256.     # List of operations AND, OR, XOR in order
  257.     operlist = [lambda x,y:x&y, lambda x,y:x|y, lambda x,y:x^y]
  258.     if rs in reg:
  259.         if rs == 'm': # ANA M, ORA M, XRA M
  260.             rs = mem[hexStr(reg['h'])+hexStr(reg['l'])]
  261.             bit(operation,rs)
  262.         else:         # ANA r, ORA r, XRA r
  263.             reg['a'] = operlist[operation](reg['a'],reg[rs])
  264.     else:             # ANI, ORI, XRI
  265.         reg['a'] = operlist[operation](reg['a'],rs)
  266.  
  267. def shift(direction, num, fill):
  268.     """Shifts 'num' in given 'direction' bit-wise after
  269.    padding it with zeroes till 'fill' number of characters"""
  270.     byte = binStr(num, fill)
  271.     if direction == 'r':
  272.         byte = byte[-1] + byte[:-1]
  273.     elif direction == 'l':
  274.         byte = byte[1:] + byte[0]
  275.     return eval('0b' + byte)
  276.  
  277. #============================= Executing function ==============================
  278.  
  279. def execute(start):
  280.     global mem,reg,flags,regPairs
  281.     pc = counter(start)     # initialize counter from 'start' address
  282.     timeSlice, t = 15, time()
  283.  
  284.     def getAddr(startFrom):
  285.         """Extract 4 byte address from address locations proceeding given
  286.        'startFrom' location in the memory, lsb then msb"""
  287.         return (hexStr(mem[hexStr(startFrom.value() + 2, 4)]) +
  288.                 hexStr(mem[hexStr(startFrom.value() + 1, 4)]))
  289.  
  290.     while mem[pc()] != 0xcf :#and (time()-t <= timeSlice):
  291.         instruction, op1, op2 = [opcode[mem[pc()]].group(i).lower() for i in [1,2,3]]
  292.         print instruction, op1, op2
  293.         if instruction == 'mov':
  294.             move(op1,op2)
  295.         elif instruction == 'mvi':
  296.             pc.next()
  297.             move(op1,mem[pc()])
  298.         elif instruction == 'lxi':
  299.             pc.next()
  300.             move(regPairs[op1],mem[pc()])
  301.             pc.next()
  302.             move(op1,mem[pc()])
  303.         elif instruction == 'ldax':
  304.             addr = hexStr(reg[op1]) + hexStr(reg[regPairs[op1]])
  305.             reg['a'] = mem[addr]
  306.         elif instruction == 'stax':
  307.             addr = hexStr(reg[op1]) + hexStr(reg[regPairs[op1]])
  308.             mem[addr] = reg['a']
  309.         elif instruction == 'lda':
  310.             move('a', mem[getAddr(pc)])
  311.             pc.next(2)
  312.         elif instruction == 'sta':
  313.             mem[getAddr(pc)] = reg['a']
  314.             pc.next(2)
  315.         elif instruction == 'lhld':
  316.             reg['l'] = mem[getAddr(pc)]
  317.             reg['h'] = mem[hexStr(eval(getAddr(pc)) + 1,4)]
  318.             pc.next(2)
  319.         elif instruction == 'shld':
  320.             mem[getAddr(pc)] = reg['l']
  321.             mem[hexStr(eval(getAddr(pc)) + 1,4)] = reg['h']
  322.         elif instruction == 'xchg':
  323.             reg['h'],reg['l'],reg['d'],reg['e'] = reg['d'],reg['e'],reg['h'],reg['l']
  324.         elif instruction in ['add','adc']:
  325.             add(op1, instruction=='adc')
  326.             flagUpdate()
  327.         elif instruction in ['adi','aci']:
  328.             pc.next()
  329.             add(mem[pc()],instruction=='aci')
  330.             flagUpdate()
  331.         elif instruction in ['sub','sbb']:
  332.             sub(op1,instruction=='sbb')
  333.             flagUpdate('szp')
  334.         elif instruction in ['sui','sbi']:
  335.             pc.next()
  336.             sub(mem[pc()],instruction=='sbi')
  337.             flagUpdate('szp')
  338.         elif  instruction == 'inr':
  339.             add(1, 0, op1)
  340.             carry = flags['cy']
  341.             flagUpdate('szpcy',op1)
  342.             flags['cy'] = carry
  343.         elif instruction == 'dcr':
  344.             add(0xff, 0, op1)
  345.             carry = flags['cy']
  346.             flagUpdate('szpcy',op1)
  347.             flags['cy'] = carry
  348.         elif instruction in ['inx','dcx']:
  349.             pair = '0x' + hexStr(reg[op1]) + hexStr(reg[regPairs[op1]])
  350.             pair = hexStr(eval(pair) + [1,-1][instruction=='dcx'])
  351.             reg[op1],reg[regPairs[op1]] = eval('0x' + pair[:2]),eval('0x' + pair[2:])
  352.         elif instruction == 'dad':
  353.             reg['l'] += reg[regPairs[op1]]
  354.             if reg['l'] >= 256:
  355.                 reg['l'] = eval('0b' + bin(reg['l'])[-8:])
  356.                 add(1,0,'h')
  357.                 flagUpdate('cy','h')
  358.             reg['h'] += reg[op1]
  359.             flagUpdate('cy','h')
  360.         elif instruction == 'daa':
  361.             if flags['ac'] or ((hexStr(reg['a']))[-1]).isalpha():
  362.                 add(6, 0)
  363.             if flags['cy'] or ((hexStr(reg['a']))[0]).isalpha():
  364.                 add(0x60, 0)
  365.             flagUpdate()
  366.         elif instruction == 'jmp':
  367.             pc.address = hexStr(eval('0x' + getAddr(pc)) - 1,4)
  368.         elif 'j' in instruction:
  369.             jump = [instruction==i for i in ['jz','jnz','jc','jnc','jpe','jpo','jm','jp']]
  370.             conditions = [bool(flags['z']),not bool(flags['z']),bool(flags['cy']),not bool(flags['cy']),\
  371.                           bool(flags['p']),not bool(flags['p']),bool(flags['s']) ,not bool(flags['s'])]
  372.             if conditions[jump.index(True)]:
  373.                 pc.address = hexStr(eval('0x' + getAddr(pc))-1, 4)
  374.             else:
  375.                 pc.next(2)
  376.         elif instruction == 'pchl':
  377.             pc.address = hexStr(reg['h'], 2) + hexStr(reg['l'], 2)
  378.             pc.address = hexStr(pc.value() - 1,4)
  379.         elif instruction in ['ana','ani']:
  380.             bit(0, ([op1,mem[hexStr(pc.value() + 1,4)]][instruction=='ani']))
  381.             flagUpdate('szp')
  382.             flags['cy'], flags['ac'] = 0, 1
  383.         elif instruction in ['ora','ori']:
  384.             bit(1, ([op1,mem[hexStr(pc.value() + 1,4)]][instruction=='ori']))
  385.             flagUpdate('szp')
  386.             flags['cy'], flags['ac'] = 0, 0
  387.         elif instruction in ['xra','xri']:
  388.             bit(2, ([op1,mem[hexStr(pc.value() + 1,4)]][instruction=='xri']))
  389.             flagUpdate('szp')
  390.             flags['cy'], flags['ac'] = 0, 0
  391.         elif instruction == 'cmp':
  392.             if op1 == 'm':
  393.                 m = mem[hexStr(reg['h'])+hexStr(reg['l'])]
  394.                 flags['cy'] = int(reg['a'] < m)
  395.                 flags['z'] = int(reg['a'] == m)
  396.             else:
  397.                 flags['cy'] = int(reg['a'] < reg[op1])
  398.                 flags['z'] = int(reg['a'] == reg[op1])
  399.         elif instruction == 'cpi':
  400.             op1 = mem[hexStr(pc.value() + 1, 4)]
  401.             flags['cy'] = int(reg['a'] < op1)
  402.             flags['z'] = int(reg['a'] == op1)
  403.         elif instruction == 'rlc':
  404.             reg['a'] = shift('l', reg['a'], 8)
  405.             flags['cy'] = binStr(reg['a'])[-1]
  406.         elif instruction == 'rrc':
  407.             reg['a'] = shift('r', reg['a'], 8)
  408.             flags['cy'] = binStr(reg['a'])[0]
  409.         elif instruction == 'ral':
  410.             reg['a'] = shift('l', reg['a'], 8)
  411.             carry, flags['cy'] = flags['cy'], int(binStr(reg['a'])[-1])
  412.             reg['a'] = eval('0b' + binStr(reg['a'])[:-1] + str(carry))
  413.         elif instruction == 'rar':
  414.             reg['a'] = shift('r', reg['a'], 8)
  415.             carry, flags['cy'] = flags['cy'], int(binStr(reg['a'])[0])
  416.             reg['a'] = eval('0b' + str(carry) + binStr(reg['a'])[1:])
  417.         elif instruction == 'cma':
  418.             reg['a'] = negate(reg['a'])
  419.         elif instruction == 'cmc':
  420.             flags['cy'] = int(not flags['cy'])
  421.         elif instruction == 'stc':
  422.             flags['cy'] = 1
  423.         pc.next()
  424.  
  425. #-------------------------------------------------------------------------------
  426. #============================= Interface Functions =============================
  427.  
  428. def drawButtons():
  429.     global buttons, buttonFrame
  430.     numPadText = ['C\nU1','D\nU2','E\nU3','F\nU4',\
  431.                   '8\nGo/H','9\nL','A\nLOAD','B\nSAVE',\
  432.                   '4\nSPH','5\nSPL','6\nPCH','7\nPCL',\
  433.                   '0\nSET','1\nCODE','2\nSTEP','3\nREG']
  434.     opPadText = "VI,DCR,EXEC,INR".split(',')
  435.     gap = 50
  436.     startX, startY = 350, 0
  437.     width, height = 100, 100
  438.     for i in range(4):
  439.         buttons.append(Button(buttonFrame, opPadText[i],
  440.                               startX - width - gap,
  441.                               startY + (height*i),
  442.                               width, height, buttonPress))
  443.     for i in range(4):
  444.         for j in range(4):
  445.             buttons.append(Button(buttonFrame, numPadText[4*i+j],
  446.                                   startX + (width*j),
  447.                                   startY + (height*i),
  448.                                   width, height, buttonPress))
  449.     buttons.append(Button(buttonFrame, "RST",
  450.                           startX - (width*2) - gap, startY,
  451.                           width-2, height-2, buttonPress))
  452.  
  453. def update(add=None):
  454.     global addressLED, contentLED, address, content, mem
  455.     if not add:
  456.         for i in range(4):
  457.             addressLED[i].colorSeg(address[len(address)-4+i])
  458.         for i in range(2):
  459.             contentLED[i].colorSeg(content[len(content)-2+i])
  460.     else:
  461.         if mem.has_key(add):
  462.             content = hexStr(mem[add])
  463.         else:
  464.             content, mem[add] = '00', 0
  465.         update()
  466.  
  467. def buttonPress(key):
  468.     global address, content, activeField, mode, mem
  469.     # print "You pressed {}\nMode: {}\nActive:{}".format(key, mode, activeField)
  470.  
  471.     if len(key) < 2 and ('0' <= key <= 'f'): # pressed key is a digt/numpad key
  472.         if mode == "reset":
  473.         # if 'reset' mode then keys have special meaning
  474.         # denoted by text blow the numbers on the keys
  475.             if key == "0": # '0' means 'SET' instruction
  476.                 activeField = "address"
  477.                 #firstEntry = True # the first entry would blank the address
  478.                 address, content = ' '*4, ' '*2
  479.                 mode = "entry"
  480.             elif key == "3": # '3' means 'REG' instruction
  481.                 mode = "reg"
  482.                 activeField = "address"
  483.                 address, content = ' '*4, ' '*2
  484.                 update()
  485.             elif key == "8": # '8' means 'GO' instruction
  486.                 address, content = ' '*4, ' '*2
  487.                 mode = "go"
  488.                 activeField = "address"
  489.             elif key == "b": # 'B' means 'SAVE' instruction
  490.                 root.iconify()
  491.                 root.update()
  492.                 fname = raw_input("Enter the name of the file to be saved as\n")
  493.                 f = open(os.path.join(os.getcwd(), 'bin\\{}'.format(fname) + '.pkl'), 'w')
  494.                 pickle.dump(mem, f)
  495.                 print "Saved successfully"
  496.                 f.close()
  497.                 root.deiconify()
  498.             elif key == "a": # 'A' means 'LOAD' instruction
  499.                 root.iconify()
  500.                 root.update()
  501.                 fname = raw_input("Enter the name of the file to be loaded\n")
  502.                 try:
  503.                     f = open(os.path.join(os.getcwd(), 'bin\\{}'.format(fname) + '.pkl'), 'r')
  504.                 except IOError:
  505.                     print "Sorry, required file could not be located"
  506.                 else:
  507.                     mem = pickle.load(f)
  508.                     print "Loaded successfully"
  509.                     f.close()
  510.                 root.deiconify()
  511.             update()
  512.  
  513.         elif mode in ["entry","go"]:
  514.         # if 'entry' mode, the numbers are appended to
  515.         # the respective field denoted by activeField variable
  516.             if activeField == "content":
  517.                 content = (content + key)[1:] # append key to current value
  518.             elif activeField == "address":
  519.                 address = (address + key)[1:] # append key to current value
  520.             update()
  521.  
  522.         elif mode == "reg":
  523.             if key == "rst":
  524.                 mode = "reset"
  525.                 address, content = 'frie', 'nd'
  526.                 activeField = ""
  527.             elif activeField == "address":
  528.                 if key in 'abcde':
  529.                     address = ' '*3 + key
  530.                     content = hexStr(reg[key], 2)
  531.                 elif key == "8":
  532.                     address = ' '*3 + 'h'
  533.                     content = hexStr(reg['h'], 2)
  534.                 elif key == '9':
  535.                     address = ' '*3 + 'l'
  536.                     content = hexStr(reg['l'], 2)
  537.                 elif key == 'f':
  538.                     address = ' '*3 + 'f'
  539.                     content = hexStr(eval('0b' + ''.join([str(flags[char]) for char
  540.                                            in 's,z,-,ac,-,p,-,cy'.split(',')])), 2)
  541.                 activeField = "content"
  542.             elif activeField == "content" and address[-1] != 'f':
  543.                 content = (content + key)[1:]
  544.             update()
  545.  
  546.  
  547.     elif key in ["inr","dcr"]: # pressed 'INR' key
  548.         diff = 1 if key == "inr" else -1
  549.         if activeField == "address":
  550.             activeField = "content"
  551.             update(address)
  552.         elif activeField == "content":
  553.             if mode == "reg":
  554.                 reg[address[-1]] = int(content,16)
  555.                 activeField ="address"
  556.                 buttonPress('abcde89f'[('abcdehlf'.index(address[-1]) + diff)%8])
  557.             else:
  558.                 try:
  559.                     mem[address] = int(content, 16)
  560.                 except ValueError:
  561.                     address, content = 'ferr', 'or'
  562.                     update()
  563.                 else:
  564.                     address = hexStr(int(address,16) + diff, 4)
  565.                     update(address)
  566.  
  567.     elif key == 'rst': # pressed 'RST' key
  568.         address, content = "frie", "nd"
  569.         mode = "reset"
  570.         update()
  571.  
  572.     elif key == "exec":
  573.         if mode == "go":
  574.             activeField = ""
  575.             pc = address
  576.             #print "Executing from {}".format(pc)
  577.             address = '   e'
  578.             update()
  579.             root.update()
  580.             t = time()
  581.             try:
  582.                 execute(pc)
  583.             except:
  584.                 address, content = 'ferr', 'or'
  585.                 update()
  586.                 print "\nUnexpected Error: ", sys.exc_info()
  587.             else:
  588.                 print "Time taken: {}".format(time()-t)
  589.                 buttonPress('rst')
  590.             #execute(pc)
  591.  
  592. #-------------------------------------------------------------------------------
  593. #=============================== User Interface ================================
  594.  
  595. root = Tk()
  596. root.title('8085 Microprocessor simulator')
  597.  
  598. screenHeight, screenWidth = root.winfo_screenheight(), root.winfo_screenwidth()
  599. windowHeight, windowWidth = int(screenHeight*(5/6.0)), int(screenWidth*(2/3.0))
  600. windowPadX, windowPadY = int(screenWidth*(1/6.0)), int(screenHeight*(1/24.0))
  601.  
  602. root.geometry('{}x{}+{}+{}'.format(windowWidth, windowHeight, windowPadX, windowPadY))
  603. root.pack_propagate(False)
  604. root.config(background = 'black')
  605.  
  606. #----------------------------------Key Bindings---------------------------------
  607. def f(e):
  608.     char = e.char
  609.     if char == '+':
  610.         buttonPress('inr')
  611.     elif char == '-':
  612.         buttonPress('dcr')
  613.     else:
  614.         buttonPress(e.char.lower())
  615.  
  616. for char in '0123456789+-abcdefABCDEF':
  617.     root.bind(char, f)
  618.  
  619. root.bind('<space>', lambda e:buttonPress('rst'))
  620. root.bind('<Return>', lambda e:buttonPress('exec'))
  621. #-------------------------------------------------------------------------------
  622.  
  623. displayFrame = Frame(root, background = 'black', height=200)
  624. displayFrame.pack(side=TOP, fill=X)
  625.  
  626. buttonFrame = Frame(root, background = 'black')
  627. buttonFrame.pack(side=TOP, fill=BOTH, expand=1)
  628.  
  629.  
  630. addressLED = [LED(displayFrame, str(i), 75*i + 200, 25, 75, 150) for i in range(4)]
  631. contentLED = [LED(displayFrame, str(i), 75*i + (200+75*4+25), 25, 75, 150) for i in range(2)]
  632. address = ""
  633. content = ""
  634. activeField = ""
  635. firstEntry = False
  636. mode = 'reset'
  637.  
  638. buttons = []
  639.  
  640.  
  641. #-------------------------------------------------------------------------------
  642. #============================ Functionality Checks =============================
  643.  
  644. address = "frie"
  645. content = "nd"
  646.  
  647. update()
  648.  
  649. def main():
  650.     drawButtons()
  651.     root.mainloop()
  652.  
  653. if __name__ == '__main__':
  654.     main()
  655.  
  656. #-------------------------------------------------------------------------------
  657.  
  658. # Todo3  Assembler
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement