[pypy-svn] r34443 - pypy/dist/pypy/jit/codegen/ppc

mwh at codespeak.net mwh at codespeak.net
Thu Nov 9 21:40:09 CET 2006


Author: mwh
Date: Thu Nov  9 21:40:06 2006
New Revision: 34443

Modified:
   pypy/dist/pypy/jit/codegen/ppc/codebuf.py
   pypy/dist/pypy/jit/codegen/ppc/instruction.py
   pypy/dist/pypy/jit/codegen/ppc/rgenop.py
Log:
first implementation of flexswitch for ppc.
i made some very silly mistakes doing this :-)


Modified: pypy/dist/pypy/jit/codegen/ppc/codebuf.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/ppc/codebuf.py	(original)
+++ pypy/dist/pypy/jit/codegen/ppc/codebuf.py	Thu Nov  9 21:40:06 2006
@@ -49,12 +49,10 @@
 
 class MachineCodeBlock:
 
-    def __init__(self, map_size):
-        assert map_size % 4 == 0
-        res = alloc(map_size)
-        self._data = cast(res, POINTER(c_int * (map_size / 4)))
-        self._size = map_size/4
-        self._pos = 0
+    def __init__(self, _data, _size, _pos):
+        self._data = _data
+        self._size = _size
+        self._pos = _pos
 
     def write(self, data):
          p = self._pos
@@ -63,9 +61,30 @@
          self._data.contents[p] = data
          self._pos = p + 1
 
+    def getpos(self):
+        return self._pos
+
+    def setpos(self, _pos):
+        self._pos = _pos
+
     def tell(self):
         baseaddr = cast(self._data, c_void_p).value
         return baseaddr + self._pos * 4
 
+    def reserve(self, _size):
+        r = MachineCodeBlock(self._data, self._pos + _size, self._pos)
+        for i in range(_size):
+            self.write(0)
+        return r
+
+class OwningMachineCodeBlock(MachineCodeBlock):
     def __del__(self):
         free(cast(self._data, PTR), self._size * 4)
+
+def new_block(size_in_bytes):
+    assert size_in_bytes % 4 == 0
+    res = alloc(size_in_bytes)
+    return OwningMachineCodeBlock(
+        cast(res, POINTER(c_int * (size_in_bytes / 4))),
+        size_in_bytes/4,
+        0)

Modified: pypy/dist/pypy/jit/codegen/ppc/instruction.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/ppc/instruction.py	(original)
+++ pypy/dist/pypy/jit/codegen/ppc/instruction.py	Thu Nov  9 21:40:06 2006
@@ -297,3 +297,18 @@
     def emit(self, asm):
         if self.reg.number != 3:
             asm.mr(r3, self.reg.number)
+
+class FakeUse(Insn):
+    """ A fake use of a var to get it into a register.  And reserving
+    a condition register field."""
+    def __init__(self, rvar, var):
+        Insn.__init__(self)
+        self.var = var
+        self.reg_args = [self.var]
+        self.reg_arg_regclasses = [GP_REGISTER]
+        self.result = rvar
+        self.result_regclass = CR_FIELD
+    def allocate(self, allocator):
+        pass
+    def emit(self, asm):
+        pass

Modified: pypy/dist/pypy/jit/codegen/ppc/rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/ppc/rgenop.py	(original)
+++ pypy/dist/pypy/jit/codegen/ppc/rgenop.py	Thu Nov  9 21:40:06 2006
@@ -260,7 +260,17 @@
         self.asm.bctr()
         self._close()
 
-##     def flexswitch(self, gv_exitswitch):
+    def flexswitch(self, gv_exitswitch):
+        # make sure the exitswitch ends the block in a register:
+        crresult = Var()
+        self.insns.append(insn.FakeUse(crresult, gv_exitswitch))
+        allocator = self.allocate_and_emit()
+        switch_mc = self.asm.mc.reserve(7 * 5 + 4)
+        self._close()
+        return FlexSwitch(self.rgenop, switch_mc,
+                          allocator.loc_of(gv_exitswitch),
+                          allocator.loc_of(crresult),
+                          allocator.var2loc)
 
     # ----------------------------------------------------------------
     # ppc-specific interface:
@@ -551,45 +561,68 @@
         if self.mcs:
             return self.mcs.pop()
         else:
-            return codebuf.MachineCodeBlock(65536)   # XXX supposed infinite for now
+            return codebuf.new_block(65536)   # XXX supposed infinite for now
 
     def close_mc(self, mc):
+##         from pypy.translator.asm.ppcgen.asmfunc import get_ppcgen
+##         print '!!!!', cast(mc._data, c_void_p).value
+##         print '!!!!', mc._data.contents[0]
+##         get_ppcgen().flush2(cast(mc._data, c_void_p).value,
+##                             mc._size*4)
         self.mcs.append(mc)
 
     def openbuilder(self):
         return Builder(self, self.open_mc())
 
-## class FlexSwitch(CodeGenSwitch):
+# a switch can take 7 instructions:
 
-##     def __init__(self, rgenop):
-##         self.rgenop = rgenop
-##         self.default_case_addr = 0
-
-##     def initialize(self, builder, gv_exitswitch):
-##         self.switch_reg = gv_exitswitch.load(builder)
-##         self.saved_state = builder._save_state()
-##         self._reserve(mc)
-
-##     def _reserve(self, mc):
-##         RESERVED = 11 # enough for 5 cases and a default
-##         pos = mc.tell()
-##         for i in range(RESERVED):
-##             mc.write(0)
-##         self.nextfreepos = pos
-##         self.endfreepos = pos + RESERVED * 4
+# load_word rSCRATCH, gv_case.value (really two instructions)
+# cmpw crf, rSWITCH, rSCRATCH
+# load_word rSCRATCH, targetaddr    (again two instructions)
+# mtctr rSCRATCH
+# beqctr crf
+
+# yay RISC :/
+
+class FlexSwitch(CodeGenSwitch):
+
+    def __init__(self, rgenop, mc, switch_reg, crf, var2loc):
+        self.rgenop = rgenop
+        self.crf = crf
+        self.switch_reg = switch_reg
+        self.var2loc = var2loc
+        self.asm = RPPCAssembler()
+        self.asm.mc = mc
+        self.default_target_addr = 0
 
 ##     def _reserve_more(self):
 ##         XXX
-##         start = self.nextfreepos
-##         end   = self.endfreepos
-##         newmc = self.rgenop.open_mc()
-##         self._reserve(newmc)
-##         self.rgenop.close_mc(newmc)
-##         fullmc = InMemoryCodeBuilder(start, end)
-##         a = RPPCAssembler()
-##         a.mc = newmc
-##         fullmc.ba(rel32(self.nextfreepos))
-##         fullmc.done()
 
-##     def add_case(self, gv_case):
-##     def add_default(self):
+    def add_case(self, gv_case):
+        targetbuilder = self.rgenop.openbuilder()
+        targetbuilder.make_fresh_from_jump(self.var2loc)
+        target_addr = targetbuilder.asm.mc.tell()
+        asm = self.asm
+        assert isinstance(gv_case, IntConst)
+        asm.load_word(rSCRATCH, gv_case.value)
+        asm.cmpw(self.crf.number, rSCRATCH, self.switch_reg.number)
+        asm.load_word(rSCRATCH, target_addr)
+        asm.mtctr(rSCRATCH)
+        asm.bcctr(12, self.crf.number*4 + 2)
+        if self.default_target_addr:
+            self._write_default()
+        return targetbuilder
+
+    def add_default(self):
+        targetbuilder = self.rgenop.openbuilder()
+        targetbuilder.make_fresh_from_jump(self.var2loc)
+        self.default_target_addr = targetbuilder.asm.mc.tell()
+        self._write_default()
+        return targetbuilder
+
+    def _write_default(self):
+        pos = self.asm.mc.getpos()
+        self.asm.load_word(rSCRATCH, self.default_target_addr)
+        self.asm.mtctr(rSCRATCH)
+        self.asm.bctr()
+        self.asm.mc.setpos(pos)



More information about the Pypy-commit mailing list