[pypy-svn] r58409 - in pypy/branch/oo-jit/pypy/jit/codegen/x86_64: . test
witulski at codespeak.net
witulski at codespeak.net
Wed Sep 24 18:20:52 CEST 2008
Author: witulski
Date: Wed Sep 24 18:20:50 2008
New Revision: 58409
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
pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_simple.py
Log:
Push and pop works (new test added)
CMP has an bug with imm32 values (e.g. CMP 42,42 == false)
JNE works (new Test added)
neg. Displacement can now be convertet
some test modified to test if there is a problem with neg. values
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 Wed Sep 24 18:20:50 2008
@@ -122,14 +122,36 @@
# FIXME: rexB?
if isinstance(arg1,Register64):
rexB, modrm1 = self.get_register_bits(arg1.reg)
-
+
# exchange the two arguments (modrm2/modrm1)
if isinstance(arg2,Immediate64):
+ new_opcode = hex(int(opcode,16)+modrm1)
+ assert len(new_opcode[2:len(new_opcode)]) == 2
self.write_rex_byte(rexW, rexR, rexX, rexB)
- self.write(opcode+chr(modrm1))
+ self.write(new_opcode[2:len(new_opcode)])
self.writeImm64(arg2.value)
return quadreg_instr
+def make_one_operand_instr_with_alternate_encoding(W = None, R = None, X = None, B = None, opcode =None, md1 = None, md2 = None):
+ def quadreg_instr(self, arg1):
+ # move the parameter
+ # to the inner function
+ modrm1 = md1
+ modrm2 = md2
+ rexW = W
+ rexR = R
+ rexX = X
+ rexB = B
+ # TODO: other cases e.g memory as operand
+ # FIXME: rexB?
+ if isinstance(arg1,Register64):
+ rexB, modrm1 = self.get_register_bits(arg1.reg)
+ new_opcode = hex(int(opcode,16)+modrm1)
+ assert len(new_opcode[2:len(new_opcode)]) == 2
+ self.write_rex_byte(rexW, rexR, rexX, rexB)
+ self.write(new_opcode[2:len(new_opcode)])
+ return quadreg_instr
+
class X86_64CodeBuilder(object):
""" creats x86_64 opcodes"""
def write(self, data):
@@ -143,7 +165,7 @@
# The opcodes differs depending on the operands
# Params:
- # W (64bit Operands), R (permits R8-R15), X (extend Index field), B (extend r/m field),
+ # W (64bit Operands), R (extends reg field), X (extend Index(SIB) field), B (extends r/m field, Base(SIB) field, opcode reg field),
# Opcode, mod, modrm1, modrm2, tttn(JUMPS), extraopcode
# FIXME: rexB is set
@@ -153,6 +175,7 @@
_AND_QWREG_QWREG = make_two_operand_instr( 1, None, 0, None, "\x21", 3, None, None)
# FIXME: rexB is set
+ # maybe a bug
_CMP_QWREG_IMM32 = make_two_operand_instr( 1, 0, 0, 1, "\x81", 3, None, 7)
_CMP_QWREG_QWREG = make_two_operand_instr( 1, None, 0, None, "\x39", 3, None, None)
# FIXME: rexB is set
@@ -164,7 +187,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,"\xB8",None,None)
+ _MOV_QWREG_IMM64 = make_two_operand_instr_with_alternate_encoding(1,0,0,None,"B8",None,None)
_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")
@@ -181,6 +204,9 @@
_POP_QWREG = make_one_operand_instr( 1, 0, 0, None, "\x8F", 3, None, 0)
_PUSH_QWREG = make_one_operand_instr( 1, 0, 0, None, "\xFF", 3, None, 6)
+ #_POP_QWREG = make_one_operand_instr_with_alternate_encoding(1,0,0,None,"58",None,None)
+ #_PUSH_QWREG = make_one_operand_instr_with_alternate_encoding(1,0,0,None,"50",None,None)
+
_SETE_8REG = make_one_operand_instr( 0, 0, 0, 0, "\x0F", 3, None, 0,4)
_SETG_8REG = make_one_operand_instr( 0, 0, 0, 0, "\x0F", 3, None, 0,15)
_SETGE_8REG = make_one_operand_instr( 0, 0, 0, 0, "\x0F", 3, None, 0,13)
@@ -223,21 +249,23 @@
# op1 is and 32bit displ
def JNE(self,op1):
+ print hex(self.tell()),": JNE to",hex(op1)
self.write("\x0F")
self.write("\x85")
self.writeImm32(op1)
- print self.tell(),": JNE to",op1
+
def OR(self, op1, op2):
method = getattr(self, "_OR"+op1.to_string()+op2.to_string())
method(op1, op2)
+ #fixme:none
def POP(self, op1):
method = getattr(self, "_POP"+op1.to_string())
method(op1)
def PUSH(self, op1):
- method = getattr(self, "_POP"+op1.to_string())
+ method = getattr(self, "_PUSH"+op1.to_string())
method(op1)
def MOV(self, op1, op2):
@@ -302,16 +330,24 @@
def get_register_bits_8Bit(self, register):
return REGISTER_MAP_8BIT[register]
- # TODO: sign extention?
+
# Parse the integervalue to an charakter
# and write it
def writeImm32(self, imm32):
x = hex(imm32)
if x[0]=='-':
- x = self.cast_to_neg_hex(int(x,16))
- # parse to string and cut "0x" off
- # fill with zeros if to short
- y = "0"*(10-len(x))+x[2:len(x)]
+ # 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
+ # fill with zeros if to short
+ y = "0"*(10-len(x))+x[2:len(x)]
+ #print "y:",y
+ #y = "00000000"
assert len(y) == 8
self.write(chr(int(y[6:8],16)))
self.write(chr(int(y[4:6],16)))
@@ -347,10 +383,9 @@
byte = mod << 6 | (reg << 3) | rm
self.write(chr(byte))
- # TODO: write me
- def cast_to_neg_hex(self,a_hex):
- #FIXME: segfault to compliment
- x = hex(18446744073709551616 +a_hex)
- y = x[16:len(x)-1]
+ # TODO: write comment
+ def cast_neg_hex32(self,a_int):
+ x = hex(int("FFFFFFFF",16)+1 +a_int)
+ y = x[2:len(x)]
return y
-
+
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 Wed Sep 24 18:20:50 2008
@@ -88,19 +88,19 @@
@specialize.arg(1)
def genop1(self, opname, gv_arg):
genmethod = getattr(self, 'op_' + opname)
- # print self.mc.tell(),":",opname
+ print hex(self.mc.tell()),":",opname," ",gv_arg.to_string()
return genmethod(gv_arg)
@specialize.arg(1)
def genop2(self, opname, gv_arg1, gv_arg2):
genmethod = getattr(self, 'op_' + opname)
- # print self.mc.tell(),":",opname
+ print hex(self.mc.tell()),":",opname," ",gv_arg1.to_string()," ",gv_arg2.to_string()
return genmethod(gv_arg1, gv_arg2)
op_int_add = make_two_argument_method("ADD")
op_int_and = make_two_argument_method("AND")
op_int_dec = make_one_argument_method("DEC")
- op_int_inc = make_one_argument_method("INC")
+ op_int_inc = make_one_argument_method("INC") #for debuging
op_int_mul = make_two_argument_method("IMUL")
op_int_neg = make_one_argument_method("NEG")
op_int_not = make_one_argument_method("NOT")
@@ -108,15 +108,16 @@
op_int_push = make_one_argument_method("PUSH")
op_int_pop = make_one_argument_method("POP")
op_int_sub = make_two_argument_method("SUB")
- op_int_xor = make_two_argument_method("XOR")
+ op_int_xor = make_two_argument_method("XOR")
#FIXME: can only jump 32bit
- def jump_if_true(self, gv_condition, args_for_jump_gv):
+ #FIXME: -6 displacement: the displ+ rip of next instr
+ def jump_if_true(self, gv_condition, args_for_jump_gv):
targetbuilder = Builder()
self.mc.CMP(gv_condition, Immediate32(0))
displ = self.calc_32bit_displacement(self.mc.tell(),targetbuilder.mc.tell())
- self.mc.JNE(displ)
- #targetbuilder.come_from(self.mc, 'JNE')
+ self.mc.JNE(displ-6)
+ #targetbuilder.come_from(self.mc, 'JNE')
return targetbuilder
def op_int_gt(self, gv_x, gv_y):
@@ -161,19 +162,21 @@
def finish_and_return(self, sigtoken, gv_returnvar):
#self.mc.write("\xB8\x0F\x00\x00\x00")
+ print hex(self.mc.tell()),": RET"
self._open()
self.mc.MOV(Register64("rax"), gv_returnvar)
self.mc.RET()
self._close()
+
# if the label is greater than 32bit
# it must be in a register
def finish_and_goto(self, outputargs_gv, target):
+ print hex(self.mc.tell()),": JMP to",hex(target.startaddr)
self._open()
gv_x = self.allocate_register()
self.mc.MOV(gv_x,Immediate64(target.startaddr))
self.mc.JMP(gv_x)
- print self.mc.tell(),": JMP to",target.startaddr
self._close()
def allocate_register(self, register=None):
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 Wed Sep 24 18:20:50 2008
@@ -1,6 +1,6 @@
import py
from pypy.rpython.lltypesystem import lltype
-from pypy.jit.codegen.x86_64.rgenop import RX86_64GenOp
+from pypy.jit.codegen.x86_64.rgenop import RX86_64GenOp, Label
from pypy.jit.codegen.test.rgenop_tests import AbstractRGenOpTestsDirect
#from pypy.jit.codegen.test.rgenop_tests import AbstractRGenOpTestsCompile
@@ -9,6 +9,47 @@
def skip(self):
py.test.skip("not implemented yet")
+
+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.finish_and_return(sigtoken, gv_x)
+ builder.end()
+ return gv_push_pop
+
+#FIXME: Jumps ever
+def make_jne(rgenop):
+ sigtoken = rgenop.sigToken(lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed))
+ builder, gv_jne, [gv_x, gv_y] = rgenop.newgraph(sigtoken, "jne")
+ builder.start_writing()
+ gv_z = builder.genop2("int_gt", gv_x, gv_y)
+ builder.mc.CMP(gv_z, rgenop.genconst(1))
+ builder.mc.JNE(6)
+ builder.genop1("int_inc",gv_y)#not executed if x<=y
+ builder.genop1("int_inc",gv_y)#not executed if x<=y
+ builder.genop1("int_inc",gv_y)
+ builder.finish_and_return(sigtoken, gv_y)
+ builder.end()
+ return gv_jne
+
+def make_jmp(rgenop):
+ sigtoken = rgenop.sigToken(lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed))
+ builder, gv_jmp, [gv_x, gv_y] = rgenop.newgraph(sigtoken, "jmp")
+ builder.start_writing()
+ gv_z = builder.genop2("int_add", gv_x, gv_y)
+ builder.finish_and_goto("",Label(builder.mc.tell()+6, [], 0))
+ gv_w = builder.genop2("int_add", gv_z, gv_y)
+ gv_v = builder.genop2("int_sub", gv_w, gv_x)
+ gv_a = builder.genop1("int_inc",gv_v)
+ gv_b = builder.genop1("int_inc",gv_a)
+ builder.finish_and_return(sigtoken, gv_a)
+ builder.end()
+ return gv_jmp
def make_one_op_instr(rgenop, instr_name):
sigtoken = rgenop.sigToken(lltype.FuncType([lltype.Signed], lltype.Signed))
@@ -30,12 +71,16 @@
builder.end()
return gv_bool_op
-def make_cmp(rgenop, which_cmp):
+def make_cmp(rgenop, which_cmp, const=None):
sigtoken = rgenop.sigToken(lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed))
builder, gv_cmp, [gv_x, gv_y] = rgenop.newgraph(sigtoken, "cmp")
builder.start_writing()
- gv_result = builder.genop2(which_cmp, gv_x, gv_y)
+ if not const == None:
+ gv_result = builder.genop2(which_cmp, gv_x, rgenop.genconst(const))
+ else:
+ gv_result = builder.genop2(which_cmp, gv_x, gv_y)
+
builder.finish_and_return(sigtoken, gv_result)
builder.end()
return gv_cmp
@@ -95,6 +140,20 @@
fnptr = self.cast(mul_function,2)
res = fnptr(1200,300)
assert res == 360000
+ res = fnptr(12345,42)
+ assert res == 518490
+ res = fnptr(12345,-42)
+ assert res == -518490
+ res = fnptr(-12345,42)
+ assert res == -518490
+ res = fnptr(-12345,-42)
+ assert res == 518490
+ res = fnptr(-12345,-9876)
+ assert res == 121919220
+ res = fnptr(-12345,9876)
+ assert res == -121919220
+ res = fnptr(12345,-9876)
+ assert res == -121919220
def test_greater(self):
rgenop = self.RGenOp()
@@ -138,6 +197,8 @@
assert res == 1
res = fnptr(4,0)
assert res == 0
+ res = fnptr(0,-4)
+ assert res == 0
res = fnptr(-4,0)
assert res == 1
@@ -153,11 +214,23 @@
assert res == 1
res = fnptr(4,0)
assert res == 1
+ res = fnptr(512,256)
+ assert res == 1
+ res = fnptr(256,512)
+ assert res == 0
+ res = fnptr(-4,253) #-4>=253
+ assert res == 0 # false
res = fnptr(-4,0)
assert res == 0
def test__equal(self):
rgenop = self.RGenOp()
+ cmp_function = make_cmp(rgenop, "int_eq",42)
+ fnptr = self.cast(cmp_function,1)
+ res = fnptr(42)
+ assert res == 1
+ res = fnptr(23)
+ assert res == 0
cmp_function = make_cmp(rgenop, "int_eq")
fnptr = self.cast(cmp_function,2)
res = fnptr(3,4) # 3==4?
@@ -170,6 +243,12 @@
assert res == 0
res = fnptr(-4,0)
assert res == 0
+ res = fnptr(252,-4)
+ assert res == 0
+ res = fnptr(-4,252)
+ assert res == 0
+ res = fnptr(244,756)
+ assert res == 0
def test_not_equal(self):
rgenop = self.RGenOp()
@@ -264,7 +343,29 @@
result = fnptr(-43)
assert result == 42
- #TODO: Test push/pop
+ # if x>y:
+ # return y+1
+ # else:
+ # return y+3
+ def test_jne(self):
+ jne_func = make_jne(self.RGenOp())
+ fnptr = self.cast(jne_func,2)
+ result = fnptr(4,1)
+ assert result == 4
+ result = fnptr(1,4)
+ assert result == 5
+
+ #def test_jmp(self):
+ # jmp_function = make_jmp(self.RGenOp())
+ # fnptr = self.cast(jmp_function,2)
+ # result = fnptr(1,2)
+ # assert result == 5
+
+ def test_push_pop(self):
+ pp_func = make_push_pop(self.RGenOp())
+ fnptr = self.cast(pp_func,1)
+ result = fnptr(1)
+ assert result == 1
test_directtesthelper_direct = skip
test_dummy_compile = skip
@@ -275,7 +376,7 @@
test_dummy_direct = skip
test_largedummy_direct = skip
test_branching_direct = skip
- ##test_goto_direct = skip##
+ test_goto_direct = skip##
test_if_direct = skip
test_switch_direct = skip
test_large_switch_direct = skip
Modified: pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_simple.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_simple.py (original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_simple.py Wed Sep 24 18:20:50 2008
@@ -21,20 +21,24 @@
return builder, fp, inputargs_gv, token
class TestSimple():
-
+
def test_add_big_num(self):
builder, fp, inputargs_gv, token = make_testbuilder(2)
genv0 = inputargs_gv[0] #the first argument "location"
genv1 = inputargs_gv[1]
genv_result = builder.genop2("int_add", genv0, genv1) #creates the addition and returns the place(register) of the result in genv_result
builder.finish_and_return(token, genv_result)
+ num = fp(1280, 20)
+ assert num == 1300
+ num = fp(1280, -80)
+ assert num == 1200
num = fp(1280, 1000)
assert num == 2280
print num
def test_add_twice(self):
builder, fp, inputargs_gv, token = make_testbuilder(2)
- genv0 = inputargs_gv[0] #the first argument "place"
+ genv0 = inputargs_gv[0] #the first argument "location"
genv1 = inputargs_gv[1]
genv2 = builder.genop2("int_add", genv0, genv1)
genv_result = builder.genop2("int_add", genv2, genv1)
@@ -49,7 +53,33 @@
assert result == -4
result = fp(0,-4) # 0+(-4)+(-4) = -8
assert result == -8
+ result = fp(1280,500) # 1280+500+500=2280
+ assert result == 2280
+ result = fp(0,252) # 0+252+252= 504
+ assert result == 504 #==0000:0001:1111:1000
+ def test_tripple_add(self):
+ builder, fp, inputargs_gv, token = make_testbuilder(2)
+ genv0 = inputargs_gv[0]
+ genv1 = inputargs_gv[1]
+ genv2 = builder.genop2("int_add", genv0, genv1)
+ genv3 = builder.genop2("int_add", genv2, genv1)
+ genv_result = builder.genop2("int_add", genv3, genv1)
+ builder.finish_and_return(token, genv_result)
+ result = fp(4, 6) # 4+6+6+6= 22
+ assert result == 22
+ result = fp(2,12) # 2+12+12+12= 38
+ assert result == 38
+ result = fp(10,-2) # 10+(-2)+(-2)+(-2) = 4
+ assert result == 4
+ result = fp(-4,0) # -4 +0+0+0 = -4
+ assert result == -4
+ result = fp(0,-4) # 0+(-4)+(-4)+(-4) = -12
+ assert result == -12
+ result = fp(1280,500) # 1280+500+500+500=2780
+ assert result == 2780
+ result = fp(0,252) # 0+252+252= 756
+ assert result == 756 #==0000:0001:1111:1000
def test_add(self):
builder, fp, inputargs_gv, token = make_testbuilder(2)
@@ -69,7 +99,7 @@
builder.finish_and_return(token, genv_result)
ten = fp(-4, -6)
assert ten == -10
- print ten
+ print ten
four = fp(-4,0)
assert four == -4
print four
@@ -86,11 +116,32 @@
def test_add_imm32(self):
builder, fp, inputargs_gv, token = make_testbuilder(1)
genv0 = inputargs_gv[0] #the first argument "location"
+ genv_result = builder.genop2("int_add", genv0, rgenop.genconst(-100000)) #creates the addition and returns the place(register) of the result in genv_result
+ builder.finish_and_return(token, genv_result)
+ num = fp(-1000) # -1000+(-100000) = -101000
+ assert num == -101000
+ print num
+ num = fp(1000) # 1000+(-100000) = -99000
+ assert num == -99000
+ print num
+ num = fp(50) # 50+(-100000) = -99950
+ assert num == -99950
+ print num
+ num = fp(-1024) # -1024+(-100000) = -1124
+ assert num == -101024
+ print num
+ builder, fp, inputargs_gv, token = make_testbuilder(1)
+ genv0 = inputargs_gv[0] #the first argument "location"
genv_result = builder.genop2("int_add", genv0, rgenop.genconst(1000)) #creates the addition and returns the place(register) of the result in genv_result
builder.finish_and_return(token, genv_result)
num = fp(1111) # 1111+1000 = 2111
assert num == 2111
print num
+ num = fp(-100) # -100+1000 = 900
+ assert num == 900
+ print num
+
+
def test_ret(self):
builder, fp, inputargs_gv, token = make_testbuilder(1)
More information about the Pypy-commit
mailing list