[pypy-svn] r67905 - in pypy/branch/remove-ri386-multimethod/pypy/jit/backend/x86: . test

arigo at codespeak.net arigo at codespeak.net
Sat Sep 26 12:09:30 CEST 2009


Author: arigo
Date: Sat Sep 26 12:09:29 2009
New Revision: 67905

Modified:
   pypy/branch/remove-ri386-multimethod/pypy/jit/backend/x86/ri386.py
   pypy/branch/remove-ri386-multimethod/pypy/jit/backend/x86/test/test_ri386.py
   pypy/branch/remove-ri386-multimethod/pypy/jit/backend/x86/test/test_ri386_auto_encoding.py
Log:
Some more instructions, and start fixing test_ri386_auto_encoding.py.


Modified: pypy/branch/remove-ri386-multimethod/pypy/jit/backend/x86/ri386.py
==============================================================================
--- pypy/branch/remove-ri386-multimethod/pypy/jit/backend/x86/ri386.py	(original)
+++ pypy/branch/remove-ri386-multimethod/pypy/jit/backend/x86/ri386.py	Sat Sep 26 12:09:29 2009
@@ -59,29 +59,19 @@
     return encode_immediate, argnum, width
 
 # ____________________________________________________________
-# Emit a mod/rm referencing a stack location
-# This depends on the fact that our function prologue contains
-# exactly 4 PUSHes.
-
-def get_ebp_ofs(position):
-    # Argument is a stack position (0, 1, 2...).
-    # Returns (ebp-16), (ebp-20), (ebp-24)...
-    # This depends on the fact that our function prologue contains
-    # exactly 4 PUSHes.
-    return -WORD * (4 + position)
+# Emit a mod/rm referencing a stack location (%ebp+arg)
 
 def single_byte(value):
     return -128 <= value < 128
 
 @specialize.arg(2)
 def encode_stack(mc, arg, allow_single_byte, orbyte):
-    offset = get_ebp_ofs(arg)
-    if allow_single_byte and single_byte(offset):
+    if allow_single_byte and single_byte(arg):
         mc.writechar(chr(0x40 | ebp | orbyte))
-        mc.writeimm8(offset)
+        mc.writeimm8(arg)
     else:
         mc.writechar(chr(0x80 | ebp | orbyte))
-        mc.writeimm32(offset)
+        mc.writeimm32(arg)
     return 0
 
 def stack(argnum, allow_single_byte=True):
@@ -109,6 +99,23 @@
     encoding_steps = unrolling_iterable(encoding_steps)
     return encode
 
+def common_modes(group):
+    base = group * 8
+    INSN_ri8 = insn('\x83', orbyte(group<<3), register(1), '\xC0',
+                    immediate(2,'b'))
+    INSN_ri32 = insn('\x81', orbyte(group<<3), register(1), '\xC0',
+                     immediate(2))
+    INSN_rr = insn(chr(base+1), register(2,8), register(1,1), '\xC0')
+    INSN_rs = insn(chr(base+3), register(1,8), stack(2))
+
+    def INSN_ri(mc, reg, immed):
+        if single_byte(immed):
+            INSN_ri8(mc, reg, immed)
+        else:
+            INSN_ri32(mc, reg, immed)
+
+    return INSN_ri, INSN_rr, INSN_rs
+
 # ____________________________________________________________
 
 
@@ -137,6 +144,12 @@
     MOV_sr = insn('\x89', register(2,8), stack(1))
     MOV_rs = insn('\x8B', register(1,8), stack(2))
 
-    NOP = insn('\x90')
+    ADD_ri, ADD_rr, ADD_rs = common_modes(0)
+    OR_ri,  OR_rr,  OR_rs  = common_modes(1)
+    AND_ri, AND_rr, AND_rs = common_modes(4)
+    SUB_ri, SUB_rr, SUB_rs = common_modes(5)
+    XOR_ri, XOR_rr, XOR_rs = common_modes(6)
+    CMP_ri, CMP_rr, CMP_rs = common_modes(7)
 
-    ADD_rr = insn('\x01', register(2,8), register(1), '\xC0')
+    NOP = insn('\x90')
+    RET = insn('\xC3')

Modified: pypy/branch/remove-ri386-multimethod/pypy/jit/backend/x86/test/test_ri386.py
==============================================================================
--- pypy/branch/remove-ri386-multimethod/pypy/jit/backend/x86/test/test_ri386.py	(original)
+++ pypy/branch/remove-ri386-multimethod/pypy/jit/backend/x86/test/test_ri386.py	Sat Sep 26 12:09:29 2009
@@ -19,7 +19,7 @@
 
 def test_mov_si():
     s = CodeBuilder()
-    s.MOV_si(5, 1<<24)
+    s.MOV_si(-36, 1<<24)
     assert s.getvalue() == '\xC7\x45\xDC\x00\x00\x00\x01'
 
 def test_mov_rr():
@@ -29,12 +29,12 @@
 
 def test_mov_sr():
     s = CodeBuilder()
-    s.MOV_sr(5, edx)
+    s.MOV_sr(-36, edx)
     assert s.getvalue() == '\x89\x55\xDC'
 
 def test_mov_rs():
     s = CodeBuilder()
-    s.MOV_rs(edx, 5)
+    s.MOV_rs(edx, -36)
     assert s.getvalue() == '\x8B\x55\xDC'
 
 def test_nop_add_rr():

Modified: pypy/branch/remove-ri386-multimethod/pypy/jit/backend/x86/test/test_ri386_auto_encoding.py
==============================================================================
--- pypy/branch/remove-ri386-multimethod/pypy/jit/backend/x86/test/test_ri386_auto_encoding.py	(original)
+++ pypy/branch/remove-ri386-multimethod/pypy/jit/backend/x86/test/test_ri386_auto_encoding.py	Sat Sep 26 12:09:29 2009
@@ -1,7 +1,6 @@
-import os, random, string, struct
+import os, random, struct
 import py
-from pypy.jit.backend.x86 import ri386 as i386
-from pypy.jit.backend.x86.ri386setup import all_instructions
+from pypy.jit.backend.x86 import ri386
 from pypy.tool.udir import udir
 
 INPUTNAME = str(udir.join('checkfile.s'))
@@ -12,61 +11,31 @@
 COUNT1 = 15
 COUNT2 = 25
 
-
-sizes = {
-    i386.EAX: 4,
-    i386.ECX: 4,
-    i386.EDX: 4,
-    i386.EBX: 4,
-    i386.ESP: 4,
-    i386.EBP: 4,
-    i386.ESI: 4,
-    i386.EDI: 4,
-
-    i386.AL: 1,
-    i386.CL: 1,
-    i386.DL: 1,
-    i386.BL: 1,
-    i386.AH: 1,
-    i386.CH: 1,
-    i386.DH: 1,
-    i386.BH: 1,
-
-    i386.REG: 4,
-    i386.MODRM: 4,
-    i386.MODRM64: 8,
-    i386.IMM32: 4,
-    i386.REG8: 1,
-    i386.MODRM8: 1,
-    i386.IMM8: 1,
-    i386.IMM16: 2,
-    #i386.REL8: 1,
-    i386.REL32: 4,
-}
-
 suffixes = {0:'', 1:'b', 2:'w', 4:'l'}
 
 def reg_tests():
-    return i386.registers[:]
+    return range(8)
 
-def reg8_tests():
-    return i386.registers8[:]
+def stack_tests():
+    return ([0, 4, -4, 124, 128, -128, -132] +
+            [random.randrange(-0x20000000, 0x20000000) * 4
+             for i in range(COUNT1)])
 
 def imm8_tests():
     v = [-128,-1,0,1,127] + [random.randrange(-127, 127) for i in range(COUNT1)]
-    return map(i386.imm8, v)
+    return v
 
 def imm16_tests():
     v = [-32768,32767] + [random.randrange(-32767, -128) for i in range(COUNT1)] \
            + [random.randrange(128, 32767) for i in range(COUNT1)]
-    return map(i386.imm16, v)
+    return v
 
 def imm32_tests():
     v = ([0x80000000, 0x7FFFFFFF, 128, 256, -129, -255] +
          [random.randrange(0,65536)<<16 |
              random.randrange(0,65536) for i in range(COUNT1)] +
          [random.randrange(128, 256) for i in range(COUNT1)])
-    return map(i386.imm32, filter(lambda x: x<-128 or x>=128, v))
+    return imm8_tests() + v
 
 def pick1(memSIB, cache=[]):
     base = random.choice([None, None, None] + i386.registers)
@@ -98,53 +67,47 @@
     return i386.registers8 + [pick1(i386.memSIB8) for i in range(COUNT2)]
 
 tests = {
-    i386.EAX: lambda: [i386.eax],
-    i386.ECX: lambda: [i386.ecx],
-    i386.EDX: lambda: [i386.edx],
-    i386.EBX: lambda: [i386.ebx],
-    i386.ESP: lambda: [i386.esp],
-    i386.EBP: lambda: [i386.ebp],
-    i386.ESI: lambda: [i386.esi],
-    i386.EDI: lambda: [i386.edi],
-
-    i386.AL: lambda: [i386.al],
-    i386.CL: lambda: [i386.cl],
-    i386.DL: lambda: [i386.dl],
-    i386.BL: lambda: [i386.bl],
-    i386.AH: lambda: [i386.ah],
-    i386.CH: lambda: [i386.ch],
-    i386.DH: lambda: [i386.dh],
-    i386.BH: lambda: [i386.bh],
-
-    i386.REG: reg_tests,
-    i386.MODRM: modrm_tests,
-    i386.MODRM64: modrm64_tests,
-    i386.XMMREG: xmm_tests,
-    i386.IMM32: imm32_tests,
-    i386.REG8: reg8_tests,
-    i386.MODRM8: modrm8_tests,
-    i386.IMM8: imm8_tests,
-    i386.IMM16: imm16_tests,
-    #i386.REL8: imm8_tests,
-    i386.REL32: lambda: [], # XXX imm32_tests,
+    'r': reg_tests,
+    's': stack_tests,
+    'i': imm32_tests,
+    }
+
+regnames = ['%eax', '%ecx', '%edx', '%ebx', '%esp', '%ebp', '%esi', '%edi']
+def assembler_operand_reg(regnum):
+    return regnames[regnum]
+
+def assembler_operand_stack(position):
+    if position == 0:
+        return '(%ebp)'
+    else:
+        return '%d(%%ebp)' % position
+
+def assembler_operand_imm(value):
+    return '$%d' % value
+
+assembler_operand = {
+    'r': assembler_operand_reg,
+    's': assembler_operand_stack,
+    'i': assembler_operand_imm,
     }
 
-def run_test(instrname, instr, args_lists):
+def run_test(instrname, argmodes, args_lists):
     global labelcount
-    instrname = instr.as_alias or instrname
     labelcount = 0
     oplist = []
     g = open(INPUTNAME, 'w')
     g.write('\x09.string "%s"\n' % BEGIN_TAG)
     for args in args_lists:
         suffix = ""
-        all = instr.as_all_suffixes
-        for m, extra in args:
-            if m in (i386.MODRM, i386.MODRM8) or all:
-                if not instrname == 'FNSTCW':
-                    suffix = suffixes[sizes[m]] + suffix
+##        all = instr.as_all_suffixes
+##        for m, extra in args:
+##            if m in (i386.MODRM, i386.MODRM8) or all:
+##                suffix = suffixes[sizes[m]] + suffix
+        if argmodes:
+            suffix = 'l'
+        
         following = ""
-        if instr.indirect:
+        if False:   # instr.indirect:
             suffix = ""
             if args[-1][0] == i386.REL32: #in (i386.REL8,i386.REL32):
                 labelcount += 1
@@ -157,15 +120,17 @@
             k = -1
         else:
             k = len(args)
-        for m, extra in args[:k]:
-            assert m != i386.REL32  #not in (i386.REL8,i386.REL32)
-        ops = [extra.assembler() for m, extra in args]
+        #for m, extra in args[:k]:
+        #    assert m != i386.REL32  #not in (i386.REL8,i386.REL32)
+        ops = []
+        for mode, v in zip(argmodes, args):
+            ops.append(assembler_operand[mode](v))
         ops.reverse()
-        op = '\x09%s%s %s%s' % (instrname, suffix, string.join(ops, ", "),
-                                following)
+        op = '\t%s%s %s%s' % (instrname.lower(), suffix,
+                              ', '.join(ops), following)
         g.write('%s\n' % op)
         oplist.append(op)
-    g.write('\x09.string "%s"\n' % END_TAG)
+    g.write('\t.string "%s"\n' % END_TAG)
     g.close()
     os.system('as "%s" -o "%s"' % (INPUTNAME, FILENAME))
     try:
@@ -174,75 +139,66 @@
         raise Exception("Assembler error")
     data = f.read()
     f.close()
-##    os.unlink(FILENAME)
-##    os.unlink(INPUTNAME)
-    i = string.find(data, BEGIN_TAG)
+    i = data.find(BEGIN_TAG)
     assert i>=0
-    j = string.find(data, END_TAG, i)
+    j = data.find(END_TAG, i)
     assert j>=0
     as_code = data[i+len(BEGIN_TAG)+1:j]
     return oplist, as_code
 
-##def getreg(m, extra):
-##    if m>=0:
-##        return m
-##    if m==i386.REG or m==i386.REG8:
-##        return extra
-##    if m==i386.MODRM or m==i386.MODRM8:
-##        if extra[0]==i386.memRegister:
-##            return extra[1][0]
-
-def rec_test_all(instrname, modes, args=[]):
+def make_all_tests(methname, modes, args=[]):
     if modes:
         m = modes[0]
-        if instrname.startswith('F') and m is i386.MODRM:
-            lst = modrm_noreg_tests()
-        else:
-            lst = tests[m]()
+        lst = tests[m]()
         random.shuffle(lst)
         result = []
-        for extra in lst:
-            result += rec_test_all(instrname, modes[1:], args+[(m,extra)])
+        for v in lst:
+            result += make_all_tests(methname, modes[1:], args+[v])
         return result
     else:
-        if instrname == "MOV":
-##            if args[0] == args[1]:
-##                return []   # MOV reg, same reg
-            if ((args[0][1] in (i386.eax, i386.al))
-                and args[1][1].assembler().lstrip('-').isdigit()):
-                return []   # MOV accum, [constant-address]
-            if ((args[1][1] in (i386.eax, i386.al))
-                and args[0][1].assembler().lstrip('-').isdigit()):
-                return []   # MOV [constant-address], accum
-        if instrname == "MOV16":
-            return []   # skipped
-        if instrname == "LEA":
-            if (args[1][1].__class__ != i386.MODRM or
-                args[1][1].is_register()):
-                return []
-        if instrname == "INT":
-            if args[0][1].value == 3:
-                return []
-        if instrname in ('SHL', 'SHR', 'SAR'):
-            if args[1][1].assembler() == '$1':
-                return []
-        if instrname in ('MOVZX', 'MOVSX'):
-            if args[1][1].width == 4:
-                return []
-        if instrname == "TEST":
-            if (args[0] != args[1] and
-                isinstance(args[0][1], i386.REG) and
-                isinstance(args[1][1], i386.REG)):
-                return []   # TEST reg1, reg2  <=>  TEST reg2, reg1
-        if instrname.endswith('cond'):
-            return []
+        # special cases
+        if methname in ('ADD_ri', 'AND_ri', 'CMP_ri', 'OR_ri',
+                        'SUB_ri', 'XOR_ri'):
+            if args[0] == ri386.eax:
+                return []     # ADD EAX, constant: there is a special encoding
+##        if methname == "MOV_":
+####            if args[0] == args[1]:
+####                return []   # MOV reg, same reg
+##            if ((args[0][1] in (i386.eax, i386.al))
+##                and args[1][1].assembler().lstrip('-').isdigit()):
+##                return []   # MOV accum, [constant-address]
+##            if ((args[1][1] in (i386.eax, i386.al))
+##                and args[0][1].assembler().lstrip('-').isdigit()):
+##                return []   # MOV [constant-address], accum
+##        if instrname == "MOV16":
+##            return []   # skipped
+##        if instrname == "LEA":
+##            if (args[1][1].__class__ != i386.MODRM or
+##                args[1][1].is_register()):
+##                return []
+##        if instrname == "INT":
+##            if args[0][1].value == 3:
+##                return []
+##        if instrname in ('SHL', 'SHR', 'SAR'):
+##            if args[1][1].assembler() == '$1':
+##                return []
+##        if instrname in ('MOVZX', 'MOVSX'):
+##            if args[1][1].width == 4:
+##                return []
+##        if instrname == "TEST":
+##            if (args[0] != args[1] and
+##                isinstance(args[0][1], i386.REG) and
+##                isinstance(args[1][1], i386.REG)):
+##                return []   # TEST reg1, reg2  <=>  TEST reg2, reg1
+##        if instrname.endswith('cond'):
+##            return []
         return [args]
 
 def hexdump(s):
-    return string.join(["%02X" % ord(c) for c in s], " ")
+    return ' '.join(["%02X" % ord(c) for c in s])
 
 
-class CodeChecker(i386.I386CodeBuilder):
+class CodeChecker(ri386.I386CodeBuilder):
     
     def __init__(self, expected):
         self.expected = expected
@@ -252,39 +208,32 @@
         self.op = op
         self.instrindex = self.index
 
-    def write(self, data):
-        end = self.index+len(data)
-        if data != self.expected[self.index:end]:
+    def writechar(self, char):
+        if char != self.expected[self.index:self.index+1]:
             print self.op
-            print "\x09from ri386.py:", hexdump(self.expected[self.instrindex:self.index] + data)+"..."
-            print "\x09from 'as':    ", hexdump(self.expected[self.instrindex:end])+"..."
+            print "\x09from ri386.py:", hexdump(self.expected[self.instrindex:self.index] + char)+"..."
+            print "\x09from 'as':    ", hexdump(self.expected[self.instrindex:self.index+1])+"..."
             raise Exception("Differs")
-        self.index += len(data)
+        self.index += 1
+
+    def done(self):
+        assert len(self.expected) == self.index
 
 
-def complete_test(instrname, instr):
-    print "Testing %s\x09(%d encodings)" % (instrname, len(instr.modes))
-    ilist = []
-    for modes in instr.modes:
-        ilist += rec_test_all(instrname, modes)
-    oplist, as_code = run_test(instrname, instr, ilist)
+def complete_test(methname):
+    if '_' in methname:
+        instrname, argmodes = methname.split('_')
+    else:
+        instrname, argmodes = methname, ''
+    print "Testing %s with argmodes=%r" % (instrname, argmodes)
+    ilist = make_all_tests(methname, argmodes)
+    oplist, as_code = run_test(instrname, argmodes, ilist)
     cc = CodeChecker(as_code)
     for op, args in zip(oplist, ilist):
         if op:
             cc.begin(op)
-            getattr(cc, instrname)(*[extra for m, extra in args])
-
-def complete_tests():
-    FORBIDDEN = ['CMOVPE', 'CMOVPO']    # why doesn't 'as' know about them?
-    items = i386.__dict__.items()
-    items.sort()
-    for key, value in items:
-        if isinstance(value, i386.Instruction):
-            if key in FORBIDDEN:
-                print "Skipped", key
-            else:
-                complete_test(key,value)
-    print "Ok."
+            getattr(cc, methname)(*args)
+    cc.done()
 
 def test_auto():
     import os
@@ -294,18 +243,15 @@
     if not data.startswith('GNU assembler'):
         py.test.skip("full tests require the GNU 'as' assembler")
 
-    def do_test(name, insn):
-        #print name
+    def do_test(name):
         if name in ('CMOVPE', 'CMOVPO'):
             py.test.skip("why doesn't 'as' know about CMOVPE/CMOVPO?")
-        complete_test(name, insn)
+        complete_test(name)
+
+    for name in all_instructions:
+        yield do_test, name
+
 
-    items = all_instructions.items()
-    items.sort()
-    for key, value in items:
-        yield do_test, key, value
-    del key, value
-
-if __name__ == "__main__":
-    #complete_test("TEST", i386.TEST)
-    complete_tests()
+all_instructions = [name for name in ri386.I386CodeBuilder.__dict__
+                    if name.split('_')[0].isupper()]
+all_instructions.sort()



More information about the Pypy-commit mailing list