# Path: mozz/location.py
# class StackOffset(RegOffset):
# 	def __init__(self, offset, size, stack_grows_down=True):
# 		self._offset = offset
# 		self._size = size
# 		self._stack_grows_down = stack_grows_down
# 
# 	def addr(self, host):
# 		sp = host.inferior().reg_sp()
# 		if self._stack_grows_down:
# 			addr = sp+self._offset
# 		else:
# 			addr = sp-self._offset
# 		return addr
# 
# 	def __str__(self):
# 		deref = "(%%sp)"
# 		if offset < 1:
# 			return deref
# 
# 		s = "0x%x" % self._offset
# 		if not self._stack_grows_down:
# 			s = "-" + s
# 
# 		return s + deref
# 
# class Register(Base):
# 	def __init__(self, name, size):
# 		'''
# 		specify size in bits
# 		'''
# 		self._name = name
# 		self._size = size # in bits
# 
# 	def name(self):
# 		return self._name
# 
# 	def size(self):
# 		return self._size
# 
# 	def __str__(self):
# 		return self._name
# 
# 	def value(self, host):
# 		v = host.inferior().reg(self._name)
# 		endian = host.session.endian()
# 		fmt = mozz.util.size_to_struct_fmt(self.size())
# 		if not fmt:
# 			raise Exception("invalid register size %d" % self._size)
# 		data = struct.pack("%s%s" % (endian.format(), fmt), v)
# 		return data
# 
# 	def set(self, host, data):
# 		endian = host.session.endian()
# 		sz = len(data) << 3
# 		fmt = mozz.util.size_to_struct_fmt(sz).upper()
# 		if not fmt:
# 			raise Exception("invalid register size %d" % sz)
# 		unpack_fmt = "%s%s" % (endian.format(), fmt)
# 		v = struct.unpack(unpack_fmt, data[0:self._size])[0]
# 		host.inferior().reg_set(self._name, v)


import mozz.err
	import mozz.system
from mozz.location import StackOffset, Register
	def set_return_value(self, val):
		self.host.inferior().reg_set("rax", val)

	def do_return(self):
		sp = self.host.inferior().reg_sp()
		en = self.host.session.endian()
		saved_pc = self.host.inferior().mem_read_uint64(sp, endian=en)
		self.host.inferior().reg_set_pc(saved_pc)

		if self.host.session.stack_grows_down():
			new_sp = sp + 8
		else:
			new_sp = sp - 8
		self.host.inferior().reg_set_sp(new_sp)

class X86SYSVConvention(Convention):

	def __init__(self, host):
		super(X86SYSVConvention, self).__init__(host)

		sgd = host.session.stack_grows_down()

		self.add_loc_entry('INTEGER', 0, Register("eax", 32))

		#ebp -> saved ebp
		#ebp + 4 -> ret
		#ebp + 8 -> arg0
		#...etc
		for i in range(1, 32):
			offset = i*4 + 4 

# Path: mozz/location.py
# class StackOffset(RegOffset):
# 	def __init__(self, offset, size, stack_grows_down=True):
# 		self._offset = offset
# 		self._size = size
# 		self._stack_grows_down = stack_grows_down
# 
# 	def addr(self, host):
# 		sp = host.inferior().reg_sp()
# 		if self._stack_grows_down:
# 			addr = sp+self._offset
# 		else:
# 			addr = sp-self._offset
# 		return addr
# 
# 	def __str__(self):
# 		deref = "(%%sp)"
# 		if offset < 1:
# 			return deref
# 
# 		s = "0x%x" % self._offset
# 		if not self._stack_grows_down:
# 			s = "-" + s
# 
# 		return s + deref
# 
# class Register(Base):
# 	def __init__(self, name, size):
# 		'''
# 		specify size in bits
# 		'''
# 		self._name = name
# 		self._size = size # in bits
# 
# 	def name(self):
# 		return self._name
# 
# 	def size(self):
# 		return self._size
# 
# 	def __str__(self):
# 		return self._name
# 
# 	def value(self, host):
# 		v = host.inferior().reg(self._name)
# 		endian = host.session.endian()
# 		fmt = mozz.util.size_to_struct_fmt(self.size())
# 		if not fmt:
# 			raise Exception("invalid register size %d" % self._size)
# 		data = struct.pack("%s%s" % (endian.format(), fmt), v)
# 		return data
# 
# 	def set(self, host, data):
# 		endian = host.session.endian()
# 		sz = len(data) << 3
# 		fmt = mozz.util.size_to_struct_fmt(sz).upper()
# 		if not fmt:
# 			raise Exception("invalid register size %d" % sz)
# 		unpack_fmt = "%s%s" % (endian.format(), fmt)
# 		v = struct.unpack(unpack_fmt, data[0:self._size])[0]
# 		host.inferior().reg_set(self._name, v)


# Path: mozz/abi/call.py
import mozz.err
	import mozz.system
from mozz.location import StackOffset, Register

	def set_return_value(self, val):
		self.host.inferior().reg_set("rax", val)

	def do_return(self):
		sp = self.host.inferior().reg_sp()
		en = self.host.session.endian()
		saved_pc = self.host.inferior().mem_read_uint64(sp, endian=en)
		self.host.inferior().reg_set_pc(saved_pc)

		if self.host.session.stack_grows_down():
			new_sp = sp + 8
		else:
			new_sp = sp - 8
		self.host.inferior().reg_set_sp(new_sp)

class X86SYSVConvention(Convention):

	def __init__(self, host):
		super(X86SYSVConvention, self).__init__(host)

		sgd = host.session.stack_grows_down()

		self.add_loc_entry('INTEGER', 0, Register("eax", 32))

		#ebp -> saved ebp
		#ebp + 4 -> ret
		#ebp + 8 -> arg0
		#...etc
		for i in range(1, 32):
			offset = i*4 + 4 

			self.add_loc_entry('INTEGER', i, StackOffset(offset, 32, sgd))