[pypy-svn] r59299 - in pypy/branch/oo-jit/pypy/jit/codegen/x86_64: . test
witulski at codespeak.net
witulski at codespeak.net
Tue Oct 21 13:39:19 CEST 2008
Author: witulski
Date: Tue Oct 21 13:39:18 2008
New Revision: 59299
Modified:
pypy/branch/oo-jit/pypy/jit/codegen/x86_64/assembler.py
pypy/branch/oo-jit/pypy/jit/codegen/x86_64/rgenop.py
pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_rgenop.py
Log:
*Stack scale calculation is now done in the assebler.
*compute moves (mapping of gv from one block to an other)
now uses location objects insted of strings
*the mapping of gv is now correct(remember locations befor the call and
restore them in start_writing
Modified: pypy/branch/oo-jit/pypy/jit/codegen/x86_64/assembler.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/x86_64/assembler.py (original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/x86_64/assembler.py Tue Oct 21 13:39:18 2008
@@ -59,7 +59,7 @@
self.write_modRM_byte(mod, modrm1, modrm2)
# no scale(has no effect on rsp), no index, base = rsp
self.write_SIB(0, 4, 4)
- self.writeImm32(arg1.location.offset)
+ self.writeImm32(8*arg1.location.offset) #8 == scale
return quadreg_instr
# exchange the two arguments (modrm2/modrm1)
@@ -94,7 +94,7 @@
self.write_modRM_byte(mod, modrm1, modrm2)
# no scale(has no effect on rsp), no index, base = rsp
self.write_SIB(0, 4, 4)
- self.writeImm32(arg2.location.offset)
+ self.writeImm32(8*arg2.location.offset) #8==scale
return quadreg_instr
@@ -213,7 +213,7 @@
_MOV_QWREG_IMM32 = make_two_operand_instr( 1, 0, 0, None, "\xC7", 3, None, 0)
_MOV_QWREG_QWREG = make_two_operand_instr( 1, None, 0, None, "\x89", 3, None, None)
_MOV_QWREG_IMM64 = make_two_operand_instr_with_alternate_encoding(1,0,0,None,"B8",None,None)
- _MOV_QWREG_STACK = make_two_operand_instr( 1, 0, 0, None, "\x8B", 2, None, 4)#4 =RSP
+ _MOV_QWREG_STACK = make_two_operand_instr( 1, 0, 0, None, "\x8B", 2, None, 4)#4==RSP
_MOV_STACK_QWREG = make_two_operand_instr( 1, 0, 0, None, "\x89", 2, None, 4)
_IDIV_QWREG = make_one_operand_instr( 1, 0, 0, None, "\xF7", 3, None, 7)
@@ -252,7 +252,7 @@
_XOR_QWREG_IMM32 = make_two_operand_instr( 1, 0, 0, None, "\x81", 3, None, 6)
_XOR_QWREG_QWREG = make_two_operand_instr( 1, None, 0, None, "\x31", 3, None, None)
- # TODO: maybe a problem with more ore less than two arg.
+ # TODO(all ops): maybe a problem with more ore less than two arg.
def ADD(self, op1, op2):
method = getattr(self, "_ADD"+op1.to_string()+op2.to_string())
method(op1, op2)
@@ -296,6 +296,7 @@
method(op1)
# 4 length of the immediate
+ # want_jump_to is an 32bit(!) adress
def JMP(self,want_jump_to):
#method = getattr(self, "_JMP"+op1.to_string())
#method(want_jump_to)
@@ -313,7 +314,7 @@
method = getattr(self, "_OR"+op1.to_string()+op2.to_string())
method(op1, op2)
- #FIXME: "POP/PUSH NONE" BUG
+ #FIXME: "POP/PUSH NONE" BUG- (maybe fixed)
def POP(self, op1):
method = getattr(self, "_POP"+op1.to_string())
method(op1)
@@ -396,9 +397,7 @@
if x[0]=='-':
# parse to string and cut "0x" off
# fill with Fs if to short
- #print "x before:",x
x = self.cast_neg_hex32(int(x,16))
- #print "x after:",x
y = "F"*(8-len(x))+x[0:len(x)]
else:
# parse to string and cut "0x" off
Modified: pypy/branch/oo-jit/pypy/jit/codegen/x86_64/rgenop.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/x86_64/rgenop.py (original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/x86_64/rgenop.py Tue Oct 21 13:39:18 2008
@@ -2,7 +2,6 @@
from pypy.rlib.objectmodel import specialize
from pypy.jit.codegen.x86_64.objmodel import IntVar, Register64, Register8, Immediate8, Immediate32, Immediate64, Stack64
from pypy.jit.codegen.x86_64.codebuf import InMemoryCodeBuilder
-#TODO: understand llTypesystem
from pypy.rpython.lltypesystem import llmemory, lltype
from pypy.jit.codegen.ia32.objmodel import LL_TO_GENVAR
from pypy.jit.codegen.model import GenLabel
@@ -82,7 +81,6 @@
MC_SIZE = 65536
- #FIXME: The MemCodeBuild. is not opend in an _open method
def __init__(self, stackdepth, used_registers=[], used_stack_pos = None):
self.stackdepth = stackdepth
self.mc = InMemoryCodeBuilder(self.MC_SIZE)
@@ -103,9 +101,12 @@
# "r14":None,
# "r15":None,
}
+ self._orig_location={}
self.known_gv = [] # contains the live genvars (used for spilling and allocation)
for reg in used_registers:
del self.freeregisters[reg.location.reg]
+ self._orig_location[reg] = reg.location
+ self.known_gv.append(reg)
if used_stack_pos == None:
self.used_stack_pos = {}
else:
@@ -176,6 +177,7 @@
registers[i] = self.move_back_to_register(registers[i], dont_alloc)
dont_alloc.append(registers[i].location.reg)
# some operations dont suppoert immediateoperands
+ # but only registers
if move_imm_too and isinstance(registers[i], Immediate32):
gv_new = self.allocate_register(None, dont_alloc)
self.mc.MOV(gv_new, registers[i])
@@ -267,21 +269,26 @@
self.mc.SETGE(IntVar(Register8("al")))
return gv_z
+ # move back the gv to orig. positions
+ # (this pos. could be changed here which
+ # could result in wrong locations of the gv)
+ def start_writing(self):
+ for i in range(len(self.known_gv)):
+ if self.known_gv[i] in self._orig_location:
+ self.known_gv[i].location = self._orig_location[self.known_gv[i]]
+
# the moves to pass arg. when making a jump to a block
# the targetvars are only copys
- # FIXME: problem with mapping of stackpositions
def _compute_moves(self, outputargs_gv, targetargs_gv):
tar2src = {}
tar2loc = {}
- src2loc = {}
+ src2loc = {}
for i in range(len(outputargs_gv)):
- target_gv = targetargs_gv[i].location.reg
- source_gv = outputargs_gv[i].location.reg
- tar2src[target_gv] = source_gv
- tar2loc[target_gv] = target_gv
- src2loc[source_gv] = source_gv
+ tar2src[targetargs_gv[i].location] = outputargs_gv[i].location
+ tar2loc[targetargs_gv[i].location] = targetargs_gv[i].location
+ src2loc[outputargs_gv[i].location] = outputargs_gv[i].location
movegen = MoveEmitter(self)
- emit_moves(movegen, [target_gv.location.reg for target_gv in targetargs_gv],
+ emit_moves(movegen, [target_gv.location for target_gv in targetargs_gv],
tar2src, tar2loc, src2loc)
return movegen.moves
@@ -302,7 +309,9 @@
jump_if_false = _new_jump("jump_if_false", 1)
jump_if_true = _new_jump('jump_if_true', 0)
- # TODO: move stackpointer
+ # moves stackpointer if there are
+ # gv on the stack which are not
+ # need anymore
def finish_and_return(self, sigtoken, gv_returnvar):
#self.mc.write("\xB8\x0F\x00\x00\x00")
self._open()
@@ -311,31 +320,32 @@
# throw them away
if not self.stackdepth == 0:
self.mc.ADD(IntVar(Register64("rsp")), Immediate32(self.stackdepth*8))
+ self.stackdepth == 0
if not gv_returnvar == None:#check void return
self.mc.MOV(gv_return, gv_returnvar)
self.mc.RET()
self._close()
- #assert self.stackdepth == 0
# FIXME: uses 32bit displ
# TODO: return also stackdepth or pop!
# if the label is greater than 32bit
# it must be in a register (not supported)
def finish_and_goto(self, outputargs_gv, target):
- #import pdb;pdb.set_trace()
self._open()
#gv_x = self.allocate_register()
#self.mc.MOV(gv_x,Immediate64(target.startaddr))
- #self.mc.JMP(gv_x)
+ #self.mc.JMP(gv_x)
moves = self._compute_moves(outputargs_gv, target.arg_positions)
for source_gv, target_gv in moves:
- self.mc.MOV(IntVar(Register64(source_gv)),IntVar(Register64(target_gv)))
+ # TODO: check for MOV(STACK,STACK)
+ self.mc.MOV(IntVar(source_gv), IntVar(target_gv))
self.mc.JMP(target.startaddr)
self._close()
# FIXME: returns only IntVars
# TODO: support the allocation of 8bit Reg
- # TODO: (Optimization)Don't remember genVars which contain konstants
+ # Don't remember genVars which contain constants(Optimization)
+ # An allocation could have spilling as sideeffect(stack mov)
def allocate_register(self, register=None, dontalloc = None):
if dontalloc is None:
dontalloc = []
@@ -397,7 +407,7 @@
def end(self):
pass
- # TODO: args_gv muste be a list of unique GenVars
+ # TODO: args_gv muste be a list of unique GenVars, dont searchs for double gv
# Spilling could change the location of a
# genVar after this Label. That will result in a
# wrong mapping in _compute_moves when leaving this block.
@@ -410,17 +420,21 @@
gv_x = self.allocate_register()
self.mc.MOV(gv_x, args_gv[i])
args_gv[i] = gv_x
- # copy the gv
+ # copy the genvars:
+ # without copying the references could be changed
+ # which can result in wrong locations of the gv
copy_args.append(IntVar(Register64(args_gv[i].location.reg)))
L = Label(self.mc.tell(), copy_args, 0)
return L
def _close(self):
- self.mc.done()
+ self.mc.done() # used for dump code (debugging)
# TODO: alloc strategy
# TODO: support 8bit reg. alloc
- # just greddy spilling
+ # just greedy spilling.
+ # moves GenVar locations on the stack
+ # to free an register
def spill_register(self, dont_spill=None):
if dont_spill is None:
dont_spill = []
@@ -438,19 +452,21 @@
raise WrongArgException("to many dont_spill/dont_alloc registers")
assert isinstance(gv_to_spill.location, Register64)
# if the register contains a genCons
- # it has not to be saved
+ # it has not to be saved on the stack
if gv_to_spill.location.throw_away:
return gv_to_spill
else:
- #search for free stack position/location
+ # search for free stack position/location
for location in range(self.stackdepth):
if location not in self.used_stack_pos.keys():
- self.mc.MOV(IntVar(Stack64(8*(self.stackdepth-location))), gv_to_spill)#8=scale
+ # a location has been found which is not the tos.
+ self.mc.MOV(IntVar(Stack64(self.stackdepth-location)), gv_to_spill)
self.used_stack_pos[location] = None
new_gv = IntVar(Register64(gv_to_spill.location.reg))
gv_to_spill.location = Stack64(location)
return new_gv
- # no free stack pos
+ # no free stack pos found
+ # use the top of stack ->push
self.used_stack_pos[self.stackdepth] = None # remember as used
self.stackdepth = self.stackdepth +1
self.mc.PUSH(gv_to_spill)
@@ -458,7 +474,9 @@
gv_to_spill.location = Stack64(self.stackdepth)
return new_gv
- # FIXME: pushed values are not allways poped (if not TOS)
+ # A GenVar which location is on the stack
+ # will be moved back to make operations posible
+ # and faster
def move_back_to_register(self, a_spilled_gv, dont_alloc):
# if a_spilled_gv is the top of stack
gv_new = self.allocate_register(None, dont_alloc)
@@ -475,7 +493,7 @@
return a_spilled_gv
else:
# else access the memory
- self.mc.MOV(gv_new, IntVar(Stack64(8*(self.stackdepth-a_spilled_gv.location.offset))))#8=scale
+ self.mc.MOV(gv_new, IntVar(Stack64(self.stackdepth-a_spilled_gv.location.offset)))
del self.used_stack_pos[a_spilled_gv.location.offset]
a_spilled_gv.location = Register64(gv_new.location.reg)
self.known_gv.remove(gv_new)
@@ -505,7 +523,6 @@
def newgraph(self, sigtoken, name):
arg_tokens, res_token = sigtoken
- #print "arg_tokens:",arg_tokens
inputargs_gv = []
builder = Builder(0) # stackdepth = 0, no used regs/mem_pos
# TODO: Builder._open()
Modified: pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_rgenop.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_rgenop.py (original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_rgenop.py Tue Oct 21 13:39:18 2008
@@ -21,7 +21,7 @@
builder.genop1("int_push", gv_x)
builder.genop1("int_push", gv_x)
builder.mc.MOV(gv_x, rgenop.genconst(42))
- builder.mc.MOV(IntVar(Stack64(8)), gv_x)
+ builder.mc.MOV(IntVar(Stack64(1)), gv_x)
builder.genop1("int_pop", gv_x)
builder.genop1("int_pop", gv_x)
builder.finish_and_return(sigtoken, gv_x)
@@ -39,7 +39,7 @@
builder.genop1("int_push", gv_y)
builder.genop1("int_inc", gv_y)
builder.genop1("int_push", gv_y)
- builder.mc.MOV(gv_x, IntVar(Stack64(8))) # rsp+8(bytes) (stack position of the first push)
+ builder.mc.MOV(gv_x, IntVar(Stack64(1))) # rsp+1 (stack position of the first push)
builder.genop1("int_pop", gv_y)
builder.genop1("int_pop", gv_y)
builder.finish_and_return(sigtoken, gv_x)
More information about the Pypy-commit
mailing list