Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # virtual machine architecture
- # ++++++++++++++++++++++++++++
- #
- # segmented memory model with 16-byte segment size (notation seg:offset)
- #
- # 4 general-purpose registers (r0-r3)
- # 2 segment registers (cs, ds equiv. to r4, r5)
- # 1 flags register (fl)
- #
- # instruction encoding
- # ++++++++++++++++++++
- #
- # byte 1 byte 2 (optional)
- # bits [ 7 6 5 4 3 2 1 0 ] [ 7 6 5 4 3 2 1 0 ]
- # opcode - - -
- # mod -
- # operand1 - - - -
- # operand2 - - - - - - - -
- #
- # operand1 is always a register index
- # operand2 is optional, depending upon the instruction set specified below
- # the value of mod alters the meaning of any operand2
- # 0: operand2 = reg ix
- # 1: operand2 = fixed immediate value or target segment (depending on instruction)
- #
- # instruction set
- # +++++++++++++++
- #
- # Notes:
- # * r1, r2 => operand 1 is register 1, operand 2 is register 2
- # * movr r1, r2 => move contents of register r2 into register r1
- #
- # opcode | instruction | operands (mod 0) | operands (mod 1)
- # -------+-------------+------------------+-----------------
- # 0x00 | jmp | r1 | r2:r1
- # 0x01 | movr | r1, r2 | rx, imm
- # 0x02 | movm | r1, [ds:r2] | [ds:r1], r2
- # 0x03 | add | r1, r2 | r1, imm
- # 0x04 | xor | r1, r2 | r1, imm
- # 0x05 | cmp | r1, r2 | r1, imm
- # 0x06 | jmpe | r1 | r2:r1
- # 0x07 | hlt | N/A | N/A
- #
- # flags
- # +++++
- #
- # cmp r1, r2 instruction results in:
- # r1 == r2 => fl = 0
- # r1 < r2 => fl = 0xff
- # r1 > r2 => fl = 1
- #
- # jmpe r1
- # => if (fl == 0) jmp r1
- # else nop
- CS = 4
- DS = 5
- class Instruction:
- def __init__(self):
- self.numbytes = 1
- self.numops = 1
- self.octet = 0
- self.opcode = 0
- self.mod = 0
- self.operand1 = 0
- self.operand2 = 0
- class Cpu:
- def __init__(self):
- self.labelstrs = \
- (
- '%02x:%04x\t%02x \t',
- '%02x:%04x\t%02x %02x\t'
- )
- self.formatstrs = \
- (
- ('jmp r%d', 'jmp 0x%02x:r%d'),
- ('movr r%d, r%d', 'movr r%d, #0x%02x'),
- ('movm r%d, [ds:r%d]', 'movm [ds:r%d], r%d'),
- ('add r%d, r%d', 'add r%d, #0x%02x'),
- ('xor r%d, r%d', 'xor r%d, #0x%02x'),
- ('cmp r%d, r%d', 'cmp r%d, #0x%02x'),
- ('jmpe r%d', 'jmpe 0x%02x:r%d'),
- ('hlt', 'hlt')
- )
- self.swapoperands = ((0, 1), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 1), (0,0))
- self.numoperands = ((1, 2), (2, 2), (2, 2), (2, 2), (2, 2), (2, 2), (1, 2), (0,0))
- self.running = False
- self.ip = 0x00
- self.r = [0x00, 0x00, 0x00, 0x00, 0x00, 0x10]
- self.fl = 0x00
- self.firmware = (0xd2ab1f05, 0xda13f110)
- self.mem = [0x31, 0x04, 0x33, 0xaa, 0x40, 0x02, 0x80, 0x03, 0x52, 0x00, 0x72, 0x01, 0x73, 0x01, 0xb2, 0x50,
- 0x30, 0x14, 0xc0, 0x01, 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x98, 0xab, 0xd9, 0xa1, 0x9f, 0xa7, 0x83, 0x83, 0xf2, 0xb1, 0x34, 0xb6, 0xe4, 0xb7, 0xca, 0xb8,
- 0xc9, 0xb8, 0x0e, 0xbd, 0x7d, 0x0f, 0xc0, 0xf1, 0xd9, 0x03, 0xc5, 0x3a, 0xc6, 0xc7, 0xc8, 0xc9,
- 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
- 0xda, 0xdb, 0xa9, 0xcd, 0xdf, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
- 0x26, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
- 0x7d, 0x1f, 0x15, 0x60, 0x4d, 0x4d, 0x52, 0x7d, 0x0e, 0x27, 0x6d, 0x10, 0x6d, 0x5a, 0x06, 0x56,
- 0x47, 0x14, 0x42, 0x0e, 0xb6, 0xb2, 0xb2, 0xe6, 0xeb, 0xb4, 0x83, 0x8e, 0xd7, 0xe5, 0xd4, 0xd9,
- 0xc3, 0xf0, 0x80, 0x95, 0xf1, 0x82, 0x82, 0x9a, 0xbd, 0x95, 0xa4, 0x8d, 0x9a, 0x2b, 0x30, 0x69,
- 0x4a, 0x69, 0x65, 0x55, 0x1c, 0x7b, 0x69, 0x1c, 0x6e, 0x04, 0x74, 0x35, 0x21, 0x26, 0x2f, 0x60,
- 0x03, 0x4e, 0x37, 0x1e, 0x33, 0x54, 0x39, 0xe6, 0xba, 0xb4, 0xa2, 0xad, 0xa4, 0xc5, 0x95, 0xc8,
- 0xc1, 0xe4, 0x8a, 0xec, 0xe7, 0x92, 0x8b, 0xe8, 0x81, 0xf0, 0xad, 0x98, 0xa4, 0xd0, 0xc0, 0x8d,
- 0xac, 0x22, 0x52, 0x65, 0x7e, 0x27, 0x2b, 0x5a, 0x12, 0x61, 0x0a, 0x01, 0x7a, 0x6b, 0x1d, 0x67,
- 0x75, 0x70, 0x6c, 0x1b, 0x11, 0x25, 0x25, 0x70, 0x7f, 0x7e, 0x67, 0x63, 0x30, 0x3c, 0x6d, 0x6a,
- 0x01, 0x51, 0x59, 0x5f, 0x56, 0x13, 0x10, 0x43, 0x19, 0x18, 0xe5, 0xe0, 0xbe, 0xbf, 0xbd, 0xe9,
- 0xf0, 0xf1, 0xf9, 0xfa, 0xab, 0x8f, 0xc1, 0xdf, 0xcf, 0x8d, 0xf8, 0xe7, 0xe2, 0xe9, 0x93, 0x8e,
- 0xec, 0xf5, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x37, 0x7a, 0x07, 0x11, 0x1f, 0x1d, 0x68, 0x25, 0x32, 0x77, 0x1e, 0x62, 0x23, 0x5b, 0x47, 0x55,
- 0x53, 0x30, 0x11, 0x42, 0xf6, 0xf1, 0xb1, 0xe6, 0xc3, 0xcc, 0xf8, 0xc5, 0xe4, 0xcc, 0xc0, 0xd3,
- 0x85, 0xfd, 0x9a, 0xe3, 0xe6, 0x81, 0xb5, 0xbb, 0xd7, 0xcd, 0x87, 0xa3, 0xd3, 0x6b, 0x36, 0x6f,
- 0x6f, 0x66, 0x55, 0x30, 0x16, 0x45, 0x5e, 0x09, 0x74, 0x5c, 0x3f, 0x29, 0x2b, 0x66, 0x3d, 0x0d,
- 0x02, 0x30, 0x28, 0x35, 0x15, 0x09, 0x15, 0xdd, 0xec, 0xb8, 0xe2, 0xfb, 0xd8, 0xcb, 0xd8, 0xd1,
- 0x8b, 0xd5, 0x82, 0xd9, 0x9a, 0xf1, 0x92, 0xab, 0xe8, 0xa6, 0xd6, 0xd0, 0x8c, 0xaa, 0xd2, 0x94,
- 0xcf, 0x45, 0x46, 0x67, 0x20, 0x7d, 0x44, 0x14, 0x6b, 0x45, 0x6d, 0x54, 0x03, 0x17, 0x60, 0x62,
- 0x55, 0x5a, 0x4a, 0x66, 0x61, 0x11, 0x57, 0x68, 0x75, 0x05, 0x62, 0x36, 0x7d, 0x02, 0x10, 0x4b,
- 0x08, 0x22, 0x42, 0x32, 0xba, 0xe2, 0xb9, 0xe2, 0xd6, 0xb9, 0xff, 0xc3, 0xe9, 0x8a, 0x8f, 0xc1,
- 0x8f, 0xe1, 0xb8, 0xa4, 0x96, 0xf1, 0x8f, 0x81, 0xb1, 0x8d, 0x89, 0xcc, 0xd4, 0x78, 0x76, 0x61,
- 0x72, 0x3e, 0x37, 0x23, 0x56, 0x73, 0x71, 0x79, 0x63, 0x7c, 0x08, 0x11, 0x20, 0x69, 0x7a, 0x14,
- 0x68, 0x05, 0x21, 0x1e, 0x32, 0x27, 0x59, 0xb7, 0xcf, 0xab, 0xdd, 0xd5, 0xcc, 0x97, 0x93, 0xf2,
- 0xe7, 0xc0, 0xeb, 0xff, 0xe9, 0xa3, 0xbf, 0xa1, 0xab, 0x8b, 0xbb, 0x9e, 0x9e, 0x8c, 0xa0, 0xc1,
- 0x9b, 0x5a, 0x2f, 0x2f, 0x4e, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
- def Fetch(self):
- instr = Instruction()
- extip = (self.r[CS] << 4) + self.ip
- instr.octet = self.mem[extip]
- instr.opcode = (instr.octet >> 5) & 0x7
- instr.mod = (instr.octet >> 4) & 0x1
- instr.operand1 = instr.octet & 0xf
- instr.numops = self.numoperands[instr.opcode][instr.mod]
- instr.numbytes = 1
- if (instr.numops == 2):
- instr.numbytes = 2
- instr.operand2 = self.mem[extip+1]
- return instr
- def Exec(self, instr):
- if self.running:
- target_set = False
- op1 = instr.operand1
- op2 = instr.operand2
- if instr.opcode == 0x00: # jmp
- self.ip = self.r[op1]
- if (instr.mod == 1):
- self.r[CS] = op2
- print 'Jump to %02x:%04x (%06x)' % (self.r[CS], self.ip, (self.r[CS] << 4) + self.ip)
- target_set = True
- elif instr.opcode == 0x01: # movr
- if (instr.mod == 0):
- # Register - replace op2 with what's in the register
- op2 = self.r[op2]
- self.r[op1] = op2
- print '0x%02x (%d) -> r%d' % (op2, op2, op1)
- elif instr.opcode == 0x02: # movm
- if (instr.mod == 0):
- # Mem to reg
- idx = (self.r[DS] << 4) + self.r[op2]
- self.r[op1] = self.mem[idx]
- print '[%02x:%02x] (0x%02x (%d)) -> r%d' % (self.r[DS], self.r[op2], self.mem[idx], self.mem[idx], op1)
- else:
- # Reg to Mem
- idx = (self.r[DS] << 4) + self.r[op1]
- self.mem[idx] = self.r[op2]
- print 'r%d (0x%02x (%d)) -> [%02x:%02x]' % (op2, self.mem[idx], self.mem[idx], self.r[DS], self.r[op1])
- elif instr.opcode == 0x03: # add
- if (instr.mod == 0):
- # Register
- self.r[op1] = (self.r[op1] + self.r[op2]) & 0xff # No overflow bit
- print 'r%d + r%d (0x%02x (%d)) -> r%d (0x%02x (%d))' % (op1, op2, self.r[op2], self.r[op2], op1, self.r[op1], self.r[op1])
- else:
- # Immediate
- self.r[op1] = (self.r[op1] + op2) & 0xff # No overflow bit
- print 'r%d + 0x%02x (%d) -> r%d (0x%02x (%d))' % (op1, op2, op2, op1, self.r[op1], self.r[op1])
- elif instr.opcode == 0x04: # xor
- if (instr.mod == 0):
- # Register
- self.r[op1] = self.r[op1] ^ self.r[op2]
- print 'r%d ^ r%d (0x%02x (%d)) -> r%d (0x%02x (%d))' % (op1, op2, self.r[op2], self.r[op2], op1, self.r[op1], self.r[op1])
- else:
- # Immediate
- self.r[op1] = self.r[op1] ^ op2
- print 'r%d ^ 0x%02x (%d) -> r%d (0x%02x (%d))' % (op1, op2, op2, op1, self.r[op1], self.r[op1])
- elif instr.opcode == 0x05: # cmp
- if (instr.mod == 0):
- # Register - replace op2 with what's in the register
- op2 = self.r[op2]
- self.fl = 1
- if (self.r[op1] == op2):
- self.fl = 0
- elif (self.r[op1] < op2):
- self.fl = 0xff
- print '0x%02x (%d) -> fl' % (self.fl, self.fl)
- elif instr.opcode == 0x06: # jmpe
- if (self.fl == 0):
- self.ip = self.r[op1]
- if (instr.mod == 1):
- self.r[CS] = op2
- print 'Jump to %02x:%04x (%06x)' % (self.r[CS], self.ip, (self.r[CS] << 4) + self.ip)
- target_set = True
- else:
- print 'Jump (nop)'
- elif instr.opcode == 0x07: # hlt
- self.running = False
- print 'Halt'
- if (not target_set):
- self.ip += instr.numbytes
- else:
- print 'CPU not running'
- def PrintInstr(self, instr):
- fmtstr = self.formatstrs[instr.opcode][instr.mod]
- lblstr = self.labelstrs[instr.numbytes - 1]
- ip = self.ip - instr.numbytes
- ioc = instr.octet
- op1 = instr.operand1
- op2 = instr.operand2
- if (instr.numops == 0):
- print (lblstr % (self.r[CS], ip, ioc)) + fmtstr
- elif (instr.numops == 1):
- print (lblstr % (self.r[CS], ip, ioc)) + (fmtstr % op1)
- elif (instr.numops == 2):
- if self.swapoperands[instr.opcode][instr.mod]:
- print (lblstr % (self.r[CS], ip, ioc, op2)) + (fmtstr % (op2, op1))
- else:
- print (lblstr % (self.r[CS], ip, ioc, op2)) + (fmtstr % (op1, op2))
- cpu = Cpu()
- cpu.running = True
- while cpu.running:
- instr = cpu.Fetch()
- cpu.Exec(instr)
- cpu.PrintInstr(instr)
- #raw_input("next...")
- print 'Exited'
- outfile = open('memdump.bin', 'w')
- for i in cpu.mem:
- outfile.write('%c' % i)
- outfile.close()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement