[pypy-svn] r58937 - in pypy/branch/oo-jit/pypy/jit/codegen/x86_64: . test
witulski at codespeak.net
witulski at codespeak.net
Fri Oct 10 20:29:09 CEST 2008
Author: witulski
Date: Fri Oct 10 20:29:08 2008
New Revision: 58937
Modified:
pypy/branch/oo-jit/pypy/jit/codegen/x86_64/assembler.py
pypy/branch/oo-jit/pypy/jit/codegen/x86_64/objmodel.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:
memory access works
Mov REG, Stack added + Tests
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 Fri Oct 10 20:29:08 2008
@@ -1,4 +1,4 @@
-from pypy.jit.codegen.x86_64.objmodel import IntVar, Register8, Register64, Immediate8, Immediate32, Immediate64
+from pypy.jit.codegen.x86_64.objmodel import IntVar, Register8, Register64, Immediate8, Immediate32, Immediate64, Stack64
# Mapping from 64Bit-Register to coding (Rex.W or Rex.B , ModRM)
REGISTER_MAP = {
@@ -74,7 +74,15 @@
# used in imul (extra long opcode)
if not extra == None:
self.write(extra)
- self.write_modRM_byte(mod, modrm2, modrm1)
+ self.write_modRM_byte(mod, modrm2, modrm1)
+ elif isinstance(arg2.location, Stack64):
+ self.write_rex_byte(rexW, rexR, rexX, rexB)
+ self.write(opcode)
+ # exchanged mod1,mod2, dont know why :)
+ self.write_modRM_byte(mod, modrm1, modrm2)
+ # no scale, no index, base = rsp
+ self.write_SIB(0, 4, 4)
+ self.writeImm32(arg2.location.offset)
return quadreg_instr
@@ -119,8 +127,8 @@
modrm1 = md1
modrm2 = md2
rexW = W
- rexR = R
- rexX = X
+ rexR = R #not used?
+ rexX = X #not used?
rexB = B
# TODO: other cases e.g memory as operand
# FIXME: rexB?
@@ -170,7 +178,7 @@
#TODO: support all combinations
# The opcodes differs depending on the operands
# Params:
- # W (64bit Operands), R (extends reg field), X (extend Index(SIB) field), B (extends r/m field, Base(SIB) field, opcode reg field),
+ # W (Width, 64bit Operands), R (Register, extends reg field), X (IndeX, extend Index(SIB) field), B (Base, extends r/m field, Base(SIB) field, opcode reg field),
# Opcode, mod, modrm1, modrm2, tttn(JUMPS), extraopcode
# FIXME: rexB is set
@@ -193,8 +201,9 @@
_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
- _IDIV_QWREG = make_one_operand_instr( 1, 0, 0, None, "\xF7", 3, None, 7)
+ _IDIV_QWREG = make_one_operand_instr( 1, 0, 0, None, "\xF7", 3, None, 7)
_IMUL_QWREG_QWREG = make_two_operand_instr( 1, None, 0, None, "\x0F", 3, None, None, None, "\xAF")
_IMUL_QWREG_IMM32 = make_two_operand_instr( 1, None, 0, None, "\x69", 3, None, "sameReg")
@@ -412,6 +421,10 @@
byte = mod << 6 | (reg << 3) | rm
self.write(chr(byte))
+ def write_SIB(self, scale, index, base):
+ byte = scale << 6 | (index << 3) | base
+ self.write(chr(byte))
+
# calc. the "Two's complement"
# and return as pos. hex value.
# This method is used to calc jump displ.
Modified: pypy/branch/oo-jit/pypy/jit/codegen/x86_64/objmodel.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/x86_64/objmodel.py (original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/x86_64/objmodel.py Fri Oct 10 20:29:08 2008
@@ -6,22 +6,25 @@
# The to_string method is used to choose the right
# method inside the assembler
-class Register64(object):
+class Location(object):
+ pass
+
+class Register64(Location):
def __init__(self, reg):
self.reg = reg
-class Register8(object):
+class Register8(Location):
def __init__(self, reg):
self.reg = reg
-class Stack64(object):
+class Stack64(Location):
def __init__(self, offset):
self.offset = offset
class IntVar(model.GenVar):
def __init__(self, location):
self.location = location
- assert isinstance(location, Register64) or isinstance(location, Register8) or isinstance(location, Stack64)
+ assert isinstance(location, Location)
def to_string(self):
if isinstance(self.location, Stack64):
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 Fri Oct 10 20:29:08 2008
@@ -1,6 +1,6 @@
from pypy.jit.codegen import model
from pypy.rlib.objectmodel import specialize
-from pypy.jit.codegen.x86_64.objmodel import IntVar, Register64, Register8, Immediate8, Immediate32, Immediate64
+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
@@ -73,7 +73,8 @@
MC_SIZE = 65536
#FIXME: The MemCodeBuild. is not opend in an _open method
- def __init__(self, used_registers=[]):
+ def __init__(self, stackdepth, used_registers=[]):
+ self.stackdepth = stackdepth
self.mc = InMemoryCodeBuilder(self.MC_SIZE)
#callee-saved registers are commented out
self.freeregisters ={
@@ -101,15 +102,21 @@
@specialize.arg(1)
def genop1(self, opname, gv_arg):
+ if isinstance(gv_arg, model.GenVar) and isinstance(gv_arg.location, Stack64):
+ move_back_to_register(gv_arg)
genmethod = getattr(self, 'op_' + opname)
return genmethod(gv_arg)
@specialize.arg(1)
def genop2(self, opname, gv_arg1, gv_arg2):
+ if isinstance(gv_arg1, model.GenVar) and isinstance(gv_arg1.location, Stack64):
+ move_back_to_register(gv_arg1)
+ if isinstance(gv_arg2, model.GenVar) and isinstance(gv_arg2.location, Stack64):
+ move_back_to_register(gv_arg2)
genmethod = getattr(self, 'op_' + opname)
return genmethod(gv_arg1, gv_arg2)
- op_int_add = make_two_argument_method("ADD")
+ op_int_add = make_two_argument_method("ADD") #TODO: use inc
op_int_and = make_two_argument_method("AND")
op_int_dec = make_one_argument_method("DEC") #for debuging
op_int_inc = make_one_argument_method("INC") #for debuging
@@ -119,7 +126,7 @@
op_int_or = make_two_argument_method("OR")
op_int_push = make_one_argument_method("PUSH") #for debuging
op_int_pop = make_one_argument_method("POP") #for debuging
- op_int_sub = make_two_argument_method("SUB")
+ op_int_sub = make_two_argument_method("SUB") # TODO: use DEC
op_int_xor = make_two_argument_method("XOR")
# TODO: support reg8
@@ -241,7 +248,7 @@
def jump(self, gv_condition, args_for_jump_gv):
# the targetbuilder must know the registers(live vars)
# of the calling block
- targetbuilder = Builder(args_for_jump_gv)
+ targetbuilder = Builder(self.stackdepth, args_for_jump_gv)
self.mc.CMP(gv_condition, Immediate32(value))
self.mc.JNE(targetbuilder.mc.tell())
return targetbuilder
@@ -257,6 +264,7 @@
self.mc.MOV(IntVar(Register64("rax")), gv_returnvar)
self.mc.RET()
self._close()
+ assert self.stackdepth == 0
#FIXME: uses 32bit displ
# if the label is greater than 32bit
@@ -320,26 +328,44 @@
# TODO: alloc strategy
# TODO: support 8bit reg. alloc
- # just greddy
+ # just greddy spilling
def spill_register(self):
# take the first gv which is not
# on the stack
gv_to_spill = None
for i in range(len(known_gv)):
- if not known_gv[i].location_type == "Stack64":
+ if not isinstance(known_gv[i].location, Stack64):
gv_to_spill = self.known_gv[i]
break
# there must be genVars which are
# inside an register so:
- assert not gv_to_spill==None
-
- #TODO: update Stackposition
+ assert isinstance(gv_to_spill.location, Register64)
+ self.stackdepth = self.stackdepth +1
self.mc.PUSH(gv_to_spill)
new_gv = IntVar(Register64(gv_to_spill.location.reg))
- gv_to_spill.location = Stack64(42) #XXX
+ gv_to_spill.location = Stack64(self.stackdepth)
return new_gv
-
+
+ def move_back_to_register(a_spilled_gv):
+ # if top of stack
+ if a_spilled_gv.location.offset == self.stackdepth:
+ gv_new = self.allocate_register()
+ self.mc.POP(gv_new)
+ self.stackdepth = self.stackdepth -1
+ assert self.stackdepth >= 0
+ #update all offsets
+ for i in range(len(known_gv)):
+ if isinstance(known_gv[i].location, Stack64):
+ known_gv[i].location.offset = known_gv[i].location.offset -1
+ a_spilled_gv = gv_new
+ # TODO: free gv_new (no double values in known_gv
+ # else access the memory
+ # FIXME: if this genVar becomes the top of stack it will never be pushed
+ else:
+ pass
+
+
class RX86_64GenOp(model.AbstractRGenOp):
@@ -365,7 +391,7 @@
arg_tokens, res_token = sigtoken
#print "arg_tokens:",arg_tokens
inputargs_gv = []
- builder = Builder()
+ builder = Builder(0) # stackdepth = 0
# TODO: Builder._open()
entrypoint = builder.mc.tell()
# from http://www.x86-64.org/documentation/abi.pdf
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 Fri Oct 10 20:29:08 2008
@@ -2,6 +2,7 @@
from pypy.rpython.lltypesystem import lltype
from pypy.jit.codegen.x86_64.rgenop import RX86_64GenOp, Label
from pypy.jit.codegen.test.rgenop_tests import AbstractRGenOpTestsDirect
+from pypy.jit.codegen.x86_64.objmodel import IntVar, Stack64
#from pypy.jit.codegen.test.rgenop_tests import AbstractRGenOpTestsCompile
# for the individual tests see
@@ -10,14 +11,32 @@
def skip(self):
py.test.skip("not implemented yet")
+# pushes/pos some values and than uses a mem access to access the stack
+def make_mem_func(rgenop):
+ sigtoken = rgenop.sigToken(lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed))
+ builder, gv_mem_func, [gv_x, gv_y] = rgenop.newgraph(sigtoken, "mem_op")
+ builder.start_writing()
+ builder.genop1("int_inc", gv_y)
+ builder.genop1("int_inc", gv_y)
+ builder.genop1("int_inc", gv_y)
+ 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.genop1("int_pop", gv_y)
+ builder.genop1("int_pop", gv_y)
+ builder.finish_and_return(sigtoken, gv_x)
+ builder.end()
+ return gv_mem_func
+
def make_push_pop(rgenop):
sigtoken = rgenop.sigToken(lltype.FuncType([lltype.Signed], lltype.Signed))
builder, gv_push_pop, [gv_x] = rgenop.newgraph(sigtoken, "push_pop")
builder.start_writing()
- gv_x = builder.genop1("int_push", gv_x)
- gv_x = builder.genop1("int_inc", gv_x)
- gv_x = builder.genop1("int_inc", gv_x)
- gv_x = builder.genop1("int_pop", gv_x)
+ builder.genop1("int_push", gv_x)
+ builder.genop1("int_inc", gv_x)
+ builder.genop1("int_inc", gv_x)
+ builder.genop1("int_pop", gv_x)
builder.finish_and_return(sigtoken, gv_x)
builder.end()
return gv_push_pop
@@ -442,6 +461,17 @@
fnptr = self.cast(pp_func,1)
result = fnptr(1)
assert result == 1
+ result = fnptr(42)
+ assert result == 42
+
+ # return
+ def test_memory_access(self):
+ mem_func = make_mem_func(self.RGenOp())
+ fnptr = self.cast(mem_func,2)
+ result = fnptr(0,0)
+ assert result == 3
+ result = fnptr(-1,2)
+ assert result == 5
# def test_invert(self):
# inv_function = make_one_op_instr(self.RGenOp(),"int_invert")
More information about the Pypy-commit
mailing list