def __init__(self): State.__init__(self) self.state.timer(20, self.lighten) self.color = pygame.Color(0, 0, 0) self.colors = [ pygame.Color(*color) for color in [(0, 40, 0), (40, 0, 0), (0, 40, 40)] ] self.block = Block()
def __init__(self, flip): # This will save the this instance to state machine State.__init__(self) self.flip = flip font = pygame.font.Font(None, 24) self.text = font.render('Press spacebar to flip', 1, (240, 240, 240)) self.text_rect = self.text.get_rect() self.text_rect.centerx = self.state.machine.rect.centerx self.text_rect.bottom = self.state.machine.rect.bottom - 2
def test_move_left(): from machine import move_left base: State result: State base = move_left(State(acc=None, index=0, array=[None], array_len=1)) result = State(acc=None, index=0, array=[None], array_len=1) assert base == result, "Move left trivial Case" base = move_left(State(acc=None, index=1, array=[None, None, None], array_len=3)) result = State(acc=None, index=0, array=[None, None, None], array_len=3) assert base == result, "Moving to left"
def test_init( mem, debug ): # instantiate architectural state with memory and reset address state = State( mem, debug, reset_addr=0x200 ) return state
def test_init(mem, debug): # inject bootstrap code into the memory for i, data in enumerate(bootstrap_code): mem.write(bootstrap_addr + i, 1, data) for i, data in enumerate(rewrite_code): mem.write(rewrite_addr + i, 1, data) # instantiate architectural state with memory and reset address state = State(mem, debug, reset_addr=0x0400) return state
def test_set_cell(): from machine import set_cell base: State result: State base = set_cell(State(acc=None, index=0, array=[1], array_len=1)) result = State(acc=None, index=0, array=[None], array_len=1) assert base == result, "Set trivial case" base = set_cell(State(acc=1, index=0, array=[None], array_len=1)) result = State(acc=1, index=0, array=[1], array_len=1) assert base == result, "Set a blank cell -> acc value" base = set_cell(State(acc="b", index=1, array=["a", None, "c"], array_len=3)) result = State(acc="b", index=1, array=["a", "b", "c"], array_len=3) assert base == result, "Setting a cell"
def test_erase_cell(): from machine import erase_cell base: State result: State base = erase_cell(State(acc=None, index=0, array=[1], array_len=1)) result = State(acc=None, index=0, array=[None], array_len=1) assert base == result, "Erase trivial case" base = erase_cell(State(acc=None, index=0, array=[None], array_len=1)) result = State(acc=None, index=0, array=[None], array_len=1) assert base == result, "Erase a blank cell -> blank cell" base = erase_cell(State(acc=None, index=1, array=["a", "b", "c"], array_len=3)) result = State(acc=None, index=1, array=["a", None, "c"], array_len=3) assert base == result, "Erasing cell value"
def test_copy_cell(): from machine import copy_cell base: State result: State base = copy_cell(State(acc=None, index=0, array=[1], array_len=1)) result = State(acc=1, index=0, array=[1], array_len=1) assert base == result, "Copy trivial case" base = copy_cell(State(acc=1, index=0, array=[None], array_len=1)) result = State(acc=None, index=0, array=[None], array_len=1) assert base == result, "Copy a blank cell -> blank acc" base = copy_cell(State(acc="a", index=1, array=["a", "b", "c"], array_len=3)) result = State(acc="b", index=1, array=["a", "b", "c"], array_len=3) assert base == result, "Copying cell value to acc"
def syscall_init(mem, breakpoint, argv, debug): #--------------------------------------------------------------------- # memory map initialization #--------------------------------------------------------------------- # TODO: for multicore allocate 8MB for each process #proc_stack_base[pid] = stack_base - pid * 8 * 1024 * 1024 # top of heap (breakpoint) # TODO: handled in load program # memory maps: 1GB above top of heap # mmap_start = mmap_end = break_point + 0x40000000 #--------------------------------------------------------------------- # stack argument initialization #--------------------------------------------------------------------- # http://articles.manugarg.com/aboutelfauxiliaryvectors.html # # contents size # # 0x7FFF.FFFF [ end marker ] 4 (NULL) # [ environment str data ] >=0 # [ arguments str data ] >=0 # [ padding ] 0-16 # [ auxv[n] data ] 8 (AT_NULL Vector) # 8*x # [ auxv[0] data ] 8 # [ envp[n] pointer ] 4 (NULL) # 4*x # [ envp[0] pointer ] 4 # [ argv[n] pointer ] 4 (NULL) # 4*x # [ argv[0] pointer ] 4 (program name) # stack ptr-> [ argc ] 4 (size of argv) # # (stack grows down!!!) # # 0x7F7F.FFFF < stack limit for pid 0 > # # auxv variables initialized by gem5, are these needed? # # - PAGESZ: system page size # - PHDR: virtual addr of program header tables # (for statically linked binaries) # - PHENT: size of program header entries in elf file # - PHNUM: number of program headers in elf file # - AT_ENRTY: program entry point # - UID: user ID # - EUID: effective user ID # - GID: group ID # - EGID: effective group ID # TODO: handle auxv, envp variables auxv = [] envp = [] argc = len(argv) def sum_(x): val = 0 for i in x: val += i return val # calculate sizes of sections # TODO: parameterize auxv/envp/argv calc for variable int size? stack_nbytes = [ 4, # end mark nbytes sum_([len(x) + 1 for x in envp]), # envp_str nbytes sum_([len(x) + 1 for x in argv]), # argv_str nbytes 0, # padding nbytes 8 * (len(auxv) + 1), # auxv nbytes 4 * (len(envp) + 1), # envp nbytes 4 * (len(argv) + 1), # argv nbytes 4 ] # argc nbytes # calculate padding to align boundary # TODO: gem5 doesn't do this step, temporarily remove it. There should # really be padding to align argv to a 16 byte boundary!!! #stack_nbytes[3] = 16 - (sum_(stack_nbytes[:3]) % 16) def round_down(val): return val & ~(page_size - 1) # calculate stack pointer based on size of storage needed for args # TODO: round to nearest page size? stack_ptr = round_down(stack_base - sum_(stack_nbytes)) offset = stack_ptr + sum_(stack_nbytes) stack_off = [] for nbytes in stack_nbytes: offset -= nbytes stack_off.append(offset) assert offset == stack_ptr #print 'stack min', hex( stack_ptr ) #print 'stack size', stack_base - stack_ptr #print 'argv', stack_nbytes[-2] #print 'envp', stack_nbytes[-3] #print 'auxv', stack_nbytes[-4] #print 'argd', stack_nbytes[-6] #print 'envd', stack_nbytes[-7] # utility functions # TODO: we can do more efficient versions of these using Memory object # (writing 4 bytes at once etc.) def str_to_mem(mem, val, addr): for i, char in enumerate(val + '\0'): mem.write(addr + i, 1, ord(char)) return addr + len(val) + 1 def int_to_mem(mem, val, addr): # TODO properly handle endianess for i in range(4): mem.write(addr + i, 1, (val >> 8 * i) & 0xFF) return addr + 4 # write end marker to memory int_to_mem(mem, 0, stack_off[0]) # write environment strings to memory envp_ptrs = [] offset = stack_off[1] for x in envp: envp_ptrs.append(offset) offset = str_to_mem(mem, x, offset) assert offset == stack_off[0] # write argument strings to memory argv_ptrs = [] offset = stack_off[2] for x in argv: argv_ptrs.append(offset) offset = str_to_mem(mem, x, offset) assert offset == stack_off[1] # write auxv vectors to memory offset = stack_off[4] for type_, value in auxv + [(0, 0)]: offset = int_to_mem(mem, type_, offset) offset = int_to_mem(mem, value, offset) assert offset == stack_off[3] # write envp pointers to memory offset = stack_off[5] for env in envp_ptrs + [0]: offset = int_to_mem(mem, env, offset) assert offset == stack_off[4] # write argv pointers to memory offset = stack_off[6] for arg in argv_ptrs + [0]: offset = int_to_mem(mem, arg, offset) assert offset == stack_off[5] # write argc to memory offset = stack_off[7] offset = int_to_mem(mem, argc, offset) assert offset == stack_off[6] # initialize processor state state = State(mem, debug, reset_addr=0x1000) # TODO: where should this go? state.breakpoint = breakpoint #print '---' #print 'argc = %d (%x)' % ( argc, stack_off[-1] ) #for i, ptr in enumerate(argv_ptrs): # print 'argv[%d] = %x (%x)' % ( i, argv_ptrs[i], stack_off[-2]+4*i ), # print len( argv[i] ), argv[i] #print 'argd = %s (%x)' % ( argv[0], stack_off[-6] ) #print '---' #print 'argv-base', hex(stack_off[-2]) #print 'envp-base', hex(stack_off[-3]) #print 'auxv-base', hex(stack_off[-4]) #print 'argd-base', hex(stack_off[-6]) #print 'envd-base', hex(stack_off[-7]) # initialize processor registers state.rf[reg_map['a0']] = argc # argument 0 reg = argc state.rf[reg_map['a1']] = stack_off[6] # argument 1 reg = argv ptr addr state.rf[reg_map['sp']] = stack_ptr # stack pointer reg return state
def __init__(self): # This will save the this instance to state machine State.__init__(self)
def syscall_init( mem, breakpoint, argv, envp, debug ): #--------------------------------------------------------------------- # stack argument initialization #--------------------------------------------------------------------- # http://articles.manugarg.com/aboutelfauxiliaryvectors.html # # contents size # # 0x7FFF.FFFF [ end marker ] 8 (NULL) # [ environment str data ] >=0 # [ arguments str data ] >=0 # [ padding ] 0-16 # [ auxv[n] data ] 8 (AT_NULL Vector) # 8*x # [ auxv[0] data ] 8 # [ envp[n] pointer ] 8 (NULL) # 8*x # [ envp[0] pointer ] 8 # [ argv[n] pointer ] 8 (NULL) # 8*x # [ argv[0] pointer ] 8 (program name) # stack ptr-> [ argc ] 8 (size of argv) # # (stack grows down!!!) # # 0x7F7F.FFFF < stack limit for pid 0 > # # auxv variables initialized by gem5, are these needed? # # - PAGESZ: system page size # - PHDR: virtual addr of program header tables # (for statically linked binaries) # - PHENT: size of program header entries in elf file # - PHNUM: number of program headers in elf file # - AT_ENRTY: program entry point # - UID: user ID # - EUID: effective user ID # - GID: group ID # - EGID: effective group ID # TODO: handle auxv, envp variables auxv = [] argc = len( argv ) def sum_( x ): val = 0 for i in x: val += i return val # calculate sizes of sections # TODO: parameterize auxv/envp/argv calc for variable int size? stack_nbytes = [ 8, # end mark nbytes sum_([len(x)+1 for x in envp]), # envp_str nbytes sum_([len(x)+1 for x in argv]), # argv_str nbytes 0, # padding nbytes 16*(len(auxv) + 1), # auxv nbytes 8*(len(envp) + 1), # envp nbytes 8*(len(argv) + 1), # argv nbytes 8 ] # argc nbytes # calculate padding to align boundary # TODO: gem5 doesn't do this step, temporarily remove it. There should # really be padding to align argv to a 16 byte boundary!!! #stack_nbytes[3] = 16 - (sum_(stack_nbytes[:3]) % 16) def round_down( val ): return val & ~(page_size - 1) # calculate stack pointer based on size of storage needed for args # TODO: round to nearest page size? stack_ptr = round_down( stack_base - sum_( stack_nbytes ) ) offset = stack_ptr + sum_( stack_nbytes ) stack_off = [] for nbytes in stack_nbytes: offset -= nbytes stack_off.append( offset ) assert offset == stack_ptr #print 'stack min', hex( stack_ptr ) #print 'stack size', stack_base - stack_ptr #print 'argv', stack_nbytes[-2] #print 'envp', stack_nbytes[-3] #print 'auxv', stack_nbytes[-4] #print 'argd', stack_nbytes[-6] #print 'envd', stack_nbytes[-7] # utility functions def str_to_mem( mem, val, addr ): for i, char in enumerate(val+'\0'): mem.write( addr + i, 1, ord( char ) ) return addr + len(val) + 1 def int_to_mem( mem, val, addr ): # TODO properly handle endianess for i in range( 8 ): mem.write( addr+i, 1, (val >> 8*i) & 0xFF ) return addr + 8 # write end marker to memory int_to_mem( mem, 0, stack_off[0] ) # write environment strings to memory envp_ptrs = [] offset = stack_off[1] for x in envp: envp_ptrs.append( offset ) offset = str_to_mem( mem, x, offset ) assert offset == stack_off[0] # write argument strings to memory argv_ptrs = [] offset = stack_off[2] for x in argv: argv_ptrs.append( offset ) offset = str_to_mem( mem, x, offset ) assert offset == stack_off[1] # write auxv vectors to memory offset = stack_off[4] for type_, value in auxv + [(0,0)]: offset = int_to_mem( mem, type_, offset ) offset = int_to_mem( mem, value, offset ) assert offset == stack_off[3] # write envp pointers to memory offset = stack_off[5] for env in envp_ptrs + [0]: offset = int_to_mem( mem, env, offset ) assert offset == stack_off[4] # write argv pointers to memory offset = stack_off[6] for arg in argv_ptrs + [0]: offset = int_to_mem( mem, arg, offset ) assert offset == stack_off[5] # write argc to memory offset = stack_off[7] offset = int_to_mem( mem, argc, offset ) assert offset == stack_off[6] # initialize processor state state = State( mem, debug, reset_addr=0x10000 ) # TODO: where should this go? state.breakpoint = r_uint( breakpoint ) #print '---' #print 'argc = %d (%x)' % ( argc, stack_off[-1] ) #for i, ptr in enumerate(argv_ptrs): # print 'argv[%d] = %x (%x)' % ( i, argv_ptrs[i], stack_off[-2]+4*i ), # print len( argv[i] ), argv[i] #print 'argd = %s (%x)' % ( argv[0], stack_off[-6] ) #print '---' #print 'argv-base', hex(stack_off[-2]) #print 'envp-base', hex(stack_off[-3]) #print 'auxv-base', hex(stack_off[-4]) #print 'argd-base', hex(stack_off[-6]) #print 'envd-base', hex(stack_off[-7]) # initialize processor registers state.rf[ reg_map['a0'] ] = argc # argument 0 reg = argc state.rf[ reg_map['a1'] ] = stack_off[6] # argument 1 reg = argv ptr addr state.rf[ reg_map['sp'] ] = stack_ptr # stack pointer reg return state # instantiate architectural state with memory and reset address return state
def syscall_init(mem, entrypoint, breakpoint, argv, envp, debug): #--------------------------------------------------------------------- # memory map initialization #--------------------------------------------------------------------- # TODO: for multicore allocate 8MB for each process #proc_stack_base[pid] = stack_base - pid * 8 * 1024 * 1024 # top of heap (breakpoint) # TODO: handled in load program # memory maps: 1GB above top of heap # mmap_start = mmap_end = break_point + 0x40000000 #--------------------------------------------------------------------- # stack argument initialization #--------------------------------------------------------------------- # http://articles.manugarg.com/aboutelfauxiliaryvectors.html # # contents size # # 0x7FFF.FFFF [ end marker ] 4 (NULL) # [ environment str data ] >=0 # [ arguments str data ] >=0 # [ padding ] 0-16 # [ auxv[n] data ] 8 (AT_NULL Vector) # 8*x # [ auxv[0] data ] 8 # [ envp[n] pointer ] 4 (NULL) # 4*x # [ envp[0] pointer ] 4 # [ argv[n] pointer ] 4 (NULL) # 4*x # [ argv[0] pointer ] 4 (program name) # stack ptr-> [ argc ] 4 (size of argv) # # (stack grows down!!!) # # 0x7F7F.FFFF < stack limit for pid 0 > # # auxv variables initialized by gem5, are these needed? # # - PAGESZ: system page size # - PHDR: virtual addr of program header tables # (for statically linked binaries) # - PHENT: size of program header entries in elf file # - PHNUM: number of program headers in elf file # - AT_ENRTY: program entry point # - UID: user ID # - EUID: effective user ID # - GID: group ID # - EGID: effective group ID # TODO: handle auxv, envp variables auxv = [] if EMULATE_GEM5: argv = argv[1:] argc = len(argv) def sum_(x): val = 0 for i in x: val += i return val # calculate sizes of sections # TODO: parameterize auxv/envp/argv calc for variable int size? stack_nbytes = [ 4, # end mark nbytes (sentry) sum_([len(x) + 1 for x in envp]), # envp_str nbytes sum_([len(x) + 1 for x in argv]), # argv_str nbytes 0, # padding nbytes 8 * (len(auxv) + 1), # auxv nbytes 4 * (len(envp) + 1), # envp nbytes 4 * (len(argv) + 1), # argv nbytes 4 ] # argc nbytes if EMULATE_SIMIT: stack_nbytes[4] = 0 # don't to auxv for simit def round_up(val): alignment = 16 return (val + alignment - 1) & ~(alignment - 1) # calculate padding to align boundary # NOTE: MIPs approach (but ignored by gem5) #stack_nbytes[3] = 16 - (sum_(stack_nbytes[:3]) % 16) # NOTE: gem5 ARM approach stack_nbytes[3] = round_up(sum_(stack_nbytes)) - sum_(stack_nbytes) if EMULATE_SIMIT: stack_nbytes[3] = 0 def round_down(val): alignment = 16 return val & ~(alignment - 1) # calculate stack pointer based on size of storage needed for args # TODO: round to nearest page size? stack_ptr = round_down(stack_base - sum_(stack_nbytes)) if EMULATE_SIMIT: stack_ptr = stack_base - MAX_ENVIRON offset = stack_ptr + sum_(stack_nbytes) # FIXME: this offset seems really wrong, but this is how gem5 does it! if EMULATE_GEM5: offset = stack_base print "XXX", offset stack_off = [] for nbytes in stack_nbytes: offset -= nbytes stack_off.append(offset) # FIXME: this is fails for GEM5's hacky offset... if not EMULATE_GEM5: assert offset == stack_ptr if debug.enabled('bootstrap'): print 'stack base', hex(stack_base) print 'stack min ', hex(stack_ptr) print 'stack size', stack_base - stack_ptr print print 'sentry ', stack_nbytes[0] print 'env d ', stack_nbytes[1] print 'arg d ', stack_nbytes[2] print 'padding', stack_nbytes[3] print 'auxv ', stack_nbytes[4] print 'envp ', stack_nbytes[5] print 'argv ', stack_nbytes[6] print 'argc ', stack_nbytes[7] # utility functions def str_to_mem(mem, val, addr): for i, char in enumerate(val + '\0'): mem.write(addr + i, 1, ord(char)) return addr + len(val) + 1 def int_to_mem(mem, val, addr): # TODO properly handle endianess for i in range(4): mem.write(addr + i, 1, (val >> 8 * i) & 0xFF) return addr + 4 # write end marker to memory int_to_mem(mem, 0, stack_off[0]) # write environment strings to memory envp_ptrs = [] offset = stack_off[1] for x in envp: envp_ptrs.append(offset) offset = str_to_mem(mem, x, offset) assert offset == stack_off[0] # write argument strings to memory argv_ptrs = [] offset = stack_off[2] for x in argv: argv_ptrs.append(offset) offset = str_to_mem(mem, x, offset) assert offset == stack_off[1] # write auxv vectors to memory offset = stack_off[4] if not EMULATE_SIMIT: for type_, value in auxv + [(0, 0)]: offset = int_to_mem(mem, type_, offset) offset = int_to_mem(mem, value, offset) assert offset == stack_off[3] # write envp pointers to memory offset = stack_off[5] for env in envp_ptrs + [0]: offset = int_to_mem(mem, env, offset) assert offset == stack_off[4] # write argv pointers to memory offset = stack_off[6] for arg in argv_ptrs + [0]: offset = int_to_mem(mem, arg, offset) assert offset == stack_off[5] # write argc to memory offset = stack_off[7] offset = int_to_mem(mem, argc, offset) assert offset == stack_off[6] # write zeros to bottom of stack # TODO: why does gem5 do this? offset = stack_off[7] - 1 while offset >= stack_ptr: mem.write(offset, 1, ord('\0')) offset -= 1 # initialize processor state state = State(mem, debug, reset_addr=0x1000) if debug.enabled('bootstrap'): print '---' #print 'argc = %d (%x)' % ( argc, stack_off[-1] ) #for i, ptr in enumerate(argv_ptrs): # print 'argv[%2d] = %x (%x)' % ( i, argv_ptrs[i], stack_off[-2]+4*i ), # print len( argv[i] ), argv[i] #print 'argd = %s (%x)' % ( argv[0], stack_off[-6] ) print '---' print 'envd-base', hex(stack_off[-7]) print 'argd-base', hex(stack_off[-6]) print 'auxv-base', hex(stack_off[-4]) print 'envp-base', hex(stack_off[-3]) print 'argv-base', hex(stack_off[-2]) print 'argc-base', hex(stack_off[-1]) print 'STACK_PTR', hex(stack_ptr) # TODO: where should this go? #state.pc = entrypoint state.breakpoint = r_uint(breakpoint) # initialize processor registers state.rf[0] = 0 # ptr to func to run when program exits, disable state.rf[1] = stack_off[6] # argument 1 reg = argv ptr addr state.rf[2] = stack_off[5] # argument 2 reg = envp ptr addr if EMULATE_SIMIT: state.rf[1] = argc # argument 1 reg = argc state.rf[2] = stack_off[6] # argument 2 reg = argv ptr addr state.rf[13] = stack_ptr # stack pointer reg state.rf[15] = entrypoint # program counter if debug.enabled('bootstrap'): state.rf.print_regs(per_row=4) print '=' * 20, 'end bootstrap', '=' * 20 return state
def syscall_init( mem, entrypoint, breakpoint, argv, envp, debug ): #--------------------------------------------------------------------- # memory map initialization #--------------------------------------------------------------------- # TODO: for multicore allocate 8MB for each process #proc_stack_base[pid] = stack_base - pid * 8 * 1024 * 1024 # top of heap (breakpoint) # TODO: handled in load program # memory maps: 1GB above top of heap # mmap_start = mmap_end = break_point + 0x40000000 #--------------------------------------------------------------------- # stack argument initialization #--------------------------------------------------------------------- # http://articles.manugarg.com/aboutelfauxiliaryvectors.html # # contents size # # 0x7FFF.FFFF [ end marker ] 4 (NULL) # [ environment str data ] >=0 # [ arguments str data ] >=0 # [ padding ] 0-16 # [ auxv[n] data ] 8 (AT_NULL Vector) # 8*x # [ auxv[0] data ] 8 # [ envp[n] pointer ] 4 (NULL) # 4*x # [ envp[0] pointer ] 4 # [ argv[n] pointer ] 4 (NULL) # 4*x # [ argv[0] pointer ] 4 (program name) # stack ptr-> [ argc ] 4 (size of argv) # # (stack grows down!!!) # # 0x7F7F.FFFF < stack limit for pid 0 > # # auxv variables initialized by gem5, are these needed? # # - PAGESZ: system page size # - PHDR: virtual addr of program header tables # (for statically linked binaries) # - PHENT: size of program header entries in elf file # - PHNUM: number of program headers in elf file # - AT_ENRTY: program entry point # - UID: user ID # - EUID: effective user ID # - GID: group ID # - EGID: effective group ID # TODO: handle auxv, envp variables auxv = [] if EMULATE_GEM5: argv = argv[1:] argc = len( argv ) def sum_( x ): val = 0 for i in x: val += i return val # calculate sizes of sections # TODO: parameterize auxv/envp/argv calc for variable int size? stack_nbytes = [ 4, # end mark nbytes (sentry) sum_([len(x)+1 for x in envp]), # envp_str nbytes sum_([len(x)+1 for x in argv]), # argv_str nbytes 0, # padding nbytes 8*(len(auxv) + 1), # auxv nbytes 4*(len(envp) + 1), # envp nbytes 4*(len(argv) + 1), # argv nbytes 4 ] # argc nbytes if EMULATE_SIMIT: stack_nbytes[4] = 0 # don't to auxv for simit def round_up( val ): alignment = 16 return (val + alignment - 1) & ~(alignment - 1) # calculate padding to align boundary # NOTE: MIPs approach (but ignored by gem5) #stack_nbytes[3] = 16 - (sum_(stack_nbytes[:3]) % 16) # NOTE: gem5 ARM approach stack_nbytes[3] = round_up( sum_(stack_nbytes) ) - sum_(stack_nbytes) if EMULATE_SIMIT: stack_nbytes[3] = 0 def round_down( val ): alignment = 16 return val & ~(alignment - 1) # calculate stack pointer based on size of storage needed for args # TODO: round to nearest page size? stack_ptr = round_down( stack_base - sum_( stack_nbytes ) ) if EMULATE_SIMIT: stack_ptr = stack_base - MAX_ENVIRON offset = stack_ptr + sum_( stack_nbytes ) # FIXME: this offset seems really wrong, but this is how gem5 does it! if EMULATE_GEM5: offset = stack_base print "XXX", offset stack_off = [] for nbytes in stack_nbytes: offset -= nbytes stack_off.append( offset ) # FIXME: this is fails for GEM5's hacky offset... if not EMULATE_GEM5: assert offset == stack_ptr if debug.enabled( 'bootstrap' ): print 'stack base', hex( stack_base ) print 'stack min ', hex( stack_ptr ) print 'stack size', stack_base - stack_ptr print print 'sentry ', stack_nbytes[0] print 'env d ', stack_nbytes[1] print 'arg d ', stack_nbytes[2] print 'padding', stack_nbytes[3] print 'auxv ', stack_nbytes[4] print 'envp ', stack_nbytes[5] print 'argv ', stack_nbytes[6] print 'argc ', stack_nbytes[7] # utility functions def str_to_mem( mem, val, addr ): for i, char in enumerate(val+'\0'): mem.write( addr + i, 1, ord( char ) ) return addr + len(val) + 1 def int_to_mem( mem, val, addr ): # TODO properly handle endianess for i in range( 4 ): mem.write( addr+i, 1, (val >> 8*i) & 0xFF ) return addr + 4 # write end marker to memory int_to_mem( mem, 0, stack_off[0] ) # write environment strings to memory envp_ptrs = [] offset = stack_off[1] for x in envp: envp_ptrs.append( offset ) offset = str_to_mem( mem, x, offset ) assert offset == stack_off[0] # write argument strings to memory argv_ptrs = [] offset = stack_off[2] for x in argv: argv_ptrs.append( offset ) offset = str_to_mem( mem, x, offset ) assert offset == stack_off[1] # write auxv vectors to memory offset = stack_off[4] if not EMULATE_SIMIT: for type_, value in auxv + [(0,0)]: offset = int_to_mem( mem, type_, offset ) offset = int_to_mem( mem, value, offset ) assert offset == stack_off[3] # write envp pointers to memory offset = stack_off[5] for env in envp_ptrs + [0]: offset = int_to_mem( mem, env, offset ) assert offset == stack_off[4] # write argv pointers to memory offset = stack_off[6] for arg in argv_ptrs + [0]: offset = int_to_mem( mem, arg, offset ) assert offset == stack_off[5] # write argc to memory offset = stack_off[7] offset = int_to_mem( mem, argc, offset ) assert offset == stack_off[6] # write zeros to bottom of stack # TODO: why does gem5 do this? offset = stack_off[7] - 1 while offset >= stack_ptr: mem.write( offset, 1, ord( '\0' ) ) offset -= 1 # initialize processor state state = State( mem, debug, reset_addr=0x1000 ) if debug.enabled( 'bootstrap' ): print '---' #print 'argc = %d (%x)' % ( argc, stack_off[-1] ) #for i, ptr in enumerate(argv_ptrs): # print 'argv[%2d] = %x (%x)' % ( i, argv_ptrs[i], stack_off[-2]+4*i ), # print len( argv[i] ), argv[i] #print 'argd = %s (%x)' % ( argv[0], stack_off[-6] ) print '---' print 'envd-base', hex(stack_off[-7]) print 'argd-base', hex(stack_off[-6]) print 'auxv-base', hex(stack_off[-4]) print 'envp-base', hex(stack_off[-3]) print 'argv-base', hex(stack_off[-2]) print 'argc-base', hex(stack_off[-1]) print 'STACK_PTR', hex( stack_ptr ) # TODO: where should this go? #state.pc = entrypoint state.breakpoint = breakpoint # initialize processor registers state.rf[ 0 ] = 0 # ptr to func to run when program exits, disable state.rf[ 1 ] = stack_off[6] # argument 1 reg = argv ptr addr state.rf[ 2 ] = stack_off[5] # argument 2 reg = envp ptr addr if EMULATE_SIMIT: state.rf[ 1 ] = argc # argument 1 reg = argc state.rf[ 2 ] = stack_off[6] # argument 2 reg = argv ptr addr state.rf[ 13 ] = stack_ptr # stack pointer reg state.rf[ 15 ] = entrypoint # program counter if debug.enabled( 'bootstrap' ): state.rf.print_regs( per_row=4 ) print '='* 20, 'end bootstrap', '='*20 return state
def __init__(self): State.__init__(self) self.color = pygame.Color(0, 40, 0)