[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