[pypy-commit] pypy ppc-backend-2: Start for float support in PPC backend.
edelsohn
noreply at buildbot.pypy.org
Mon Apr 23 19:55:40 CEST 2012
Author: edelsohn
Branch: ppc-backend-2
Changeset: r54689:00899aeb3dbb
Date: 2012-04-23 13:54 -0400
http://bitbucket.org/pypy/pypy/changeset/00899aeb3dbb/
Log: Start for float support in PPC backend.
diff --git a/pypy/jit/backend/ppc/helper/assembler.py b/pypy/jit/backend/ppc/helper/assembler.py
--- a/pypy/jit/backend/ppc/helper/assembler.py
+++ b/pypy/jit/backend/ppc/helper/assembler.py
@@ -6,12 +6,15 @@
import pypy.jit.backend.ppc.register as r
from pypy.rpython.lltypesystem import rffi, lltype
-def gen_emit_cmp_op(condition, signed=True):
+def gen_emit_cmp_op(condition, signed=True, fp=False):
def f(self, op, arglocs, regalloc):
l0, l1, res = arglocs
# do the comparison
- self.mc.cmp_op(0, l0.value, l1.value,
- imm=l1.is_imm(), signed=signed)
+ if fp == True:
+ self.mc.fcmpu(0, l0.value, l1.value)
+ else:
+ self.mc.cmp_op(0, l0.value, l1.value,
+ imm=l1.is_imm(), signed=signed)
# After the comparison, place the result
# in the first bit of the CR
if condition == c.LT or condition == c.U_LT:
diff --git a/pypy/jit/backend/ppc/helper/regalloc.py b/pypy/jit/backend/ppc/helper/regalloc.py
--- a/pypy/jit/backend/ppc/helper/regalloc.py
+++ b/pypy/jit/backend/ppc/helper/regalloc.py
@@ -1,5 +1,4 @@
-from pypy.jit.metainterp.history import ConstInt
-from pypy.jit.metainterp.history import Box
+from pypy.jit.metainterp.history import ConstInt, Box, FLOAT
IMM_SIZE = 2 ** 15 - 1
@@ -84,3 +83,41 @@
self.possibly_free_var(op.result)
return [reg1, reg2, res]
return f
+
+def prepare_float_op(name=None, base=True, float_result=True, guard=False):
+ if guard:
+ def f(self, op, guard_op):
+ locs = []
+ loc1 = self._ensure_value_is_boxed(op.getarg(0))
+ locs.append(loc1)
+ if base:
+ loc2 = self._ensure_value_is_boxed(op.getarg(1))
+ locs.append(loc2)
+ self.possibly_free_vars_for_op(op)
+ self.free_temp_vars()
+ if guard_op is None:
+ res = self.force_allocate_reg(op.result)
+ assert float_result == (op.result.type == FLOAT)
+ locs.append(res)
+ return locs
+ else:
+ args = self._prepare_guard(guard_op, locs)
+ return args
+ else:
+ def f(self, op):
+ locs = []
+ loc1 = self._ensure_value_is_boxed(op.getarg(0))
+ locs.append(loc1)
+ if base:
+ loc2 = self._ensure_value_is_boxed(op.getarg(1))
+ locs.append(loc2)
+ self.possibly_free_vars_for_op(op)
+ self.free_temp_vars()
+ res = self.force_allocate_reg(op.result)
+ assert float_result == (op.result.type == FLOAT)
+ locs.append(res)
+ return locs
+ if name:
+ f.__name__ = name
+ return f
+
diff --git a/pypy/jit/backend/ppc/locations.py b/pypy/jit/backend/ppc/locations.py
--- a/pypy/jit/backend/ppc/locations.py
+++ b/pypy/jit/backend/ppc/locations.py
@@ -4,8 +4,10 @@
# XXX import from arch.py, currently we have a circular import
if sys.maxint == (2**31 - 1):
WORD = 4
+ FWORD = 8
else:
WORD = 8
+ FWORD = 8
DWORD = 2 * WORD
class AssemblerLocation(object):
@@ -49,7 +51,7 @@
class FPRegisterLocation(RegisterLocation):
_immutable_ = True
type = FLOAT
- width = DWORD
+ width = FWORD
def __repr__(self):
return 'fp%d' % self.value
@@ -83,6 +85,28 @@
def as_key(self):
return self.value + 40
+class ConstFloatLoc(AssemblerLocation):
+ """This class represents an imm float value which is stored in memory at
+ the address stored in the field value"""
+ _immutable_ = True
+ width = FWORD
+ type = FLOAT
+
+ def __init__(self, value):
+ self.value = value
+
+ def getint(self):
+ return self.value
+
+ def __repr__(self):
+ return "imm_float(stored at %d)" % (self.value)
+
+ def is_imm_float(self):
+ return True
+
+ def as_key(self):
+ return self.value
+
class StackLocation(AssemblerLocation):
_immutable_ = True
diff --git a/pypy/jit/backend/ppc/opassembler.py b/pypy/jit/backend/ppc/opassembler.py
--- a/pypy/jit/backend/ppc/opassembler.py
+++ b/pypy/jit/backend/ppc/opassembler.py
@@ -174,6 +174,53 @@
l0, res = arglocs
self.mc.not_(res.value, l0.value)
+class FloatOpAssembler(object):
+ _mixin_ = True
+
+ def emit_float_add(self, op, argsloc, regalloc):
+ l0, l1, res = arglocs
+ self.mc.fadd(res.value, l0.value, l1.value)
+
+ def emit_float_sub(self, op, argsloc, regalloc):
+ l0, l1, res = arglocs
+ self.mc.fsub(res.value, l0.value, l1.value)
+
+ def emit_float_mul(self, op, argsloc, regalloc):
+ l0, l1, res = arglocs
+ self.mc.fmul(res.value, l0.value, l1.value)
+
+ def emit_float_truediv(self, op, argsloc, regalloc):
+ l0, l1, res = arglocs
+ self.mc.fdiv(res.value, l0.value, l1.value)
+
+ def emit_float_neg(self, op, argsloc, regalloc):
+ l0, res = arglocs
+ self.mc.fneg(res.value, l0.value)
+
+ def emit_float_abs(self, op, argsloc, regalloc):
+ l0, res = arglocs
+ self.mc.fabs(res.value, l0.value)
+
+ def emit_float_sqrt(self, op, argsloc, regalloc):
+ l0, res = arglocs
+ self.mc.fsqrt(res.value, l0.value)
+
+ emit_float_le = gen_emit_cmp_op(c.LE, fp=True)
+ emit_float_lt = gen_emit_cmp_op(c.LT, fp=True)
+ emit_float_gt = gen_emit_cmp_op(c.GT, fp=True)
+ emit_float_ge = gen_emit_cmp_op(c.GE, fp=True)
+ emit_float_eq = gen_emit_cmp_op(c.EQ, fp=True)
+ emit_float_ne = gen_emit_cmp_op(c.NE, fp=True)
+
+ def emit_op_cast_float_to_int(self, op, arglocs, regalloc):
+ l0, temp_loc, res = arglocs
+ self.mc.fctidz(temp_loc.value, l0.value)
+ self.mc.mfprgpr(res.value, temp_loc.value)
+
+ def emit_op_cast_int_to_float(self, op, arglocs, regalloc):
+ l0, temp_loc, res = arglocs
+ self.mc.mgprfpr(temp_loc.value, l0.value)
+ self.mc.fcfid(res.value, temp_loc.value)
class GuardOpAssembler(object):
@@ -1254,7 +1301,7 @@
MiscOpAssembler, FieldOpAssembler,
ArrayOpAssembler, StrOpAssembler,
UnicodeOpAssembler, ForceOpAssembler,
- AllocOpAssembler):
+ AllocOpAssembler, FloatOpAssembler):
def nop(self):
self.mc.ori(0, 0, 0)
diff --git a/pypy/jit/backend/ppc/regalloc.py b/pypy/jit/backend/ppc/regalloc.py
--- a/pypy/jit/backend/ppc/regalloc.py
+++ b/pypy/jit/backend/ppc/regalloc.py
@@ -8,7 +8,8 @@
prepare_unary_int_op,
prepare_binary_int_op,
prepare_binary_int_op_with_imm,
- prepare_unary_cmp)
+ prepare_unary_cmp,
+ prepare_float_op)
from pypy.jit.metainterp.history import (Const, ConstInt, ConstPtr,
Box, BoxPtr,
INT, REF, FLOAT)
@@ -41,6 +42,57 @@
def __repr__(self):
return "<TempPtr at %s>" % (id(self),)
+class TempFloat(TempBox):
+ type = FLOAT
+
+ def __repr__(self):
+ return "<TempFloat at %s>" % (id(self),)
+
+
+class FPRegisterManager(RegisterManager):
+ all_regs = r.ALL_FLOAT_REGS
+ box_types = [FLOAT]
+ save_around_call_regs = r.VOLATILES_FLOAT
+
+ def convert_to_imm(self, c):
+ adr = self.assembler.datablockwrapper.malloc_aligned(8, 8)
+ x = c.getfloatstorage()
+ rffi.cast(rffi.CArrayPtr(long.FLOATSTORAGE), adr)[0] = x
+ return locations.ConstFloatLoc(adr)
+
+ def __init__(self, longevity, frame_manager=None, assembler=None):
+ RegisterManager.__init__(self, longevity, frame_manager, assembler)
+
+ def after_call(self, v):
+ """ Adjust registers according to the result of the call,
+ which is in variable v.
+ """
+ self._check_type(v)
+ r = self.force_allocate_reg(v)
+ return r
+
+ def ensure_value_is_boxed(self, thing, forbidden_vars=[]):
+ loc = None
+ if isinstance(thing, Const):
+ assert isinstance(thing, ConstFloat)
+ loc = self.get_scratch_reg(FLOAT, self.temp_boxes + forbidden_vars)
+ immvalue = self.convert_to_imm(thing)
+ self.assembler.load(loc, immvalue)
+ else:
+ loc = self.make_sure_var_in_reg(thing,
+ forbidden_vars=self.temp_boxes + forbidden_vars)
+ return loc
+
+ def get_scratch_reg(self, type=FLOAT, forbidden_vars=[],
+ selected_reg=None):
+ assert type == FLOAT # for now
+ box = TempFloat()
+ self.temp_boxes.append(box)
+ reg = self.force_allocate_reg(box, forbidden_vars=forbidden_vars,
+ selected_reg=selected_reg)
+ return reg
+
+
class PPCRegisterManager(RegisterManager):
all_regs = r.MANAGED_REGS
box_types = None # or a list of acceptable types
@@ -131,21 +183,15 @@
@staticmethod
def frame_pos(loc, type):
num_words = PPCFrameManager.frame_size(type)
- if type == FLOAT:
- assert 0, "not implemented yet"
return locations.StackLocation(loc, num_words=num_words, type=type)
@staticmethod
def frame_size(type):
- if type == FLOAT:
- assert 0, "TODO"
return 1
@staticmethod
def get_loc_index(loc):
assert loc.is_stack()
- if loc.type == FLOAT:
- assert 0, "not implemented yet"
return loc.position
class Regalloc(object):
@@ -164,6 +210,7 @@
self.last_real_usage = last_real_usage
fm = self.frame_manager
asm = self.assembler
+ self.fprm = FPRegisterManager(longevity, fm, asm)
self.rm = PPCRegisterManager(longevity, fm, asm)
def prepare_loop(self, inputargs, operations):
@@ -182,12 +229,11 @@
cur_frame_pos = -self.assembler.OFFSET_STACK_ARGS // WORD + 1
for box in inputargs:
assert isinstance(box, Box)
- # handle inputargs in argument registers
- if box.type == FLOAT and arg_index % 2 != 0:
- assert 0, "not implemented yet"
if arg_index < n_register_args:
if box.type == FLOAT:
- assert 0, "not implemented yet"
+ loc = r.PARAM_FPREGS[arg_index]
+ self.try_allocate_reg(box, selected_reg=loc)
+ arg_index += 1
else:
loc = r.PARAM_REGS[arg_index]
self.try_allocate_reg(box, selected_reg=loc)
@@ -195,7 +241,13 @@
else:
# treat stack args as stack locations with a negative offset
if box.type == FLOAT:
- assert 0, "not implemented yet"
+ if IS_PPC_32:
+ cur_frame_pos -= 2
+ else:
+ cur_frame_pos -= 1
+ if count % 2 != 0: # Stack argument alignment
+ cur_frame_pos -= 1
+ count = 0
else:
cur_frame_pos -= 1
count += 1
@@ -255,21 +307,24 @@
def _check_invariants(self):
self.rm._check_invariants()
+ self.fprm._check_invariants()
def loc(self, var):
if var.type == FLOAT:
- assert 0, "not implemented yet"
- return self.rm.loc(var)
+ return self.fprm.loc(var)
+ else:
+ return self.rm.loc(var)
def position(self):
return self.rm.position
def next_instruction(self):
self.rm.next_instruction()
+ self.fprm.next_instruction()
def force_spill_var(self, var):
if var.type == FLOAT:
- assert 0, "not implemented yet"
+ self.fprm.force_spill_var(var)
else:
self.rm.force_spill_var(var)
@@ -278,30 +333,32 @@
def after_call(self, v):
if v.type == FLOAT:
- assert 0, "not implemented yet"
+ return self.fprm.after_call(v)
else:
return self.rm.after_call(v)
def call_result_location(self, v):
if v.type == FLOAT:
- assert 0, "not implemented yet"
+ return self.fprm.call_result_location(v)
else:
return self.rm.call_result_location(v)
def _ensure_value_is_boxed(self, thing, forbidden_vars=[]):
if thing.type == FLOAT:
- assert 0, "not implemented yet"
+ return self.fprm.ensure_value_is_boxed(thing, forbidden_vars)
else:
return self.rm.ensure_value_is_boxed(thing, forbidden_vars)
def get_scratch_reg(self, type, forbidden_vars=[], selected_reg=None):
if type == FLOAT:
- assert 0, "not implemented yet"
+ return self.fprm.get_scratch_reg(type, forbidden_vars,
+ selected_reg)
else:
return self.rm.get_scratch_reg(type, forbidden_vars, selected_reg)
def free_temp_vars(self):
self.rm.free_temp_vars()
+ self.fprm.free_temp_vars()
def make_sure_var_in_reg(self, var, forbidden_vars=[],
selected_reg=None, need_lower_byte=False):
@@ -315,11 +372,12 @@
if isinstance(value, ConstInt):
return self.rm.convert_to_imm(value)
else:
- assert 0, "not implemented yet"
+ assert isinstance(value, ConstFloat)
+ return self.fprm.convert_to_imm(value)
def _sync_var(self, v):
if v.type == FLOAT:
- assert 0, "not implemented yet"
+ self.fprm._sync_var(v)
else:
self.rm._sync_var(v)
@@ -373,6 +431,65 @@
prepare_int_is_true = prepare_unary_cmp()
prepare_int_is_zero = prepare_unary_cmp()
+ prepare_float_add = prepare_float_op(name='prepare_float_add')
+ prepare_float_sub = prepare_float_op(name='prepare_float_sub')
+ prepare_float_mul = prepare_float_op(name='prepare_float_mul')
+ prepare_float_truediv = prepare_float_op(name='prepare_float_truediv')
+
+ prepare_float_lt = prepare_float_op(float_result=False,
+ name='prepare_op_float_lt')
+ prepare_float_le = prepare_float_op(float_result=False,
+ name='prepare_op_float_le')
+ prepare_float_eq = prepare_float_op(float_result=False,
+ name='prepare_op_float_eq')
+ prepare_float_ne = prepare_float_op(float_result=False,
+ name='prepare_op_float_ne')
+ prepare_float_gt = prepare_float_op(float_result=False,
+ name='prepare_op_float_gt')
+ prepare_float_ge = prepare_float_op(float_result=False,
+ name='prepare_op_float_ge')
+ prepare_float_neg = prepare_float_op(base=False,
+ name='prepare_op_float_neg')
+ prepare_float_abs = prepare_float_op(base=False,
+ name='prepare_op_float_abs')
+
+ prepare_guard_float_lt = prepare_float_op(guard=True,
+ float_result=False, name='prepare_guard_float_lt')
+ prepare_guard_float_le = prepare_float_op(guard=True,
+ float_result=False, name='prepare_guard_float_le')
+ prepare_guard_float_eq = prepare_float_op(guard=True,
+ float_result=False, name='prepare_guard_float_eq')
+ prepare_guard_float_ne = prepare_float_op(guard=True,
+ float_result=False, name='prepare_guard_float_ne')
+ prepare_guard_float_gt = prepare_float_op(guard=True,
+ float_result=False, name='prepare_guard_float_gt')
+ prepare_guard_float_ge = prepare_float_op(guard=True,
+ float_result=False, name='prepare_guard_float_ge')
+
+ def prepare_math_sqrt(self, op):
+ loc = self._ensure_value_is_boxed(op.getarg(1))
+ self.possibly_free_vars_for_op(op)
+ self.free_temp_vars()
+ res = self.fprm.force_allocate_reg(op.result)
+ self.possibly_free_var(op.result)
+ return [loc, res]
+
+ def prepare_cast_float_to_int(self, op):
+ loc1 = self._ensure_value_is_boxed(op.getarg(0))
+ temp_loc = self.get_scratch_reg(FLOAT)
+ self.possibly_free_vars_for_op(op)
+ self.free_temp_vars()
+ res = self.rm.force_allocate_reg(op.result)
+ return [loc1, temp_loc, res]
+
+ def prepare_cast_int_to_float(self, op):
+ loc1 = self._ensure_value_is_boxed(op.getarg(0))
+ temp_loc = self.get_scratch_reg(FLOAT)
+ self.possibly_free_vars_for_op(op)
+ self.free_temp_vars()
+ res = self.fprm.force_allocate_reg(op.result)
+ return [loc1, temp_loc, res]
+
def prepare_finish(self, op):
args = [None] * (op.numargs() + 1)
for i in range(op.numargs()):
@@ -776,6 +893,7 @@
for i in range(op.numargs()):
args.append(self.loc(op.getarg(i)))
# spill variables that need to be saved around calls
+ self.fprm.before_call(save_all_regs=save_all_regs)
if not save_all_regs:
gcrootmap = self.assembler.cpu.gc_ll_descr.gcrootmap
if gcrootmap and gcrootmap.is_shadow_stack:
diff --git a/pypy/jit/backend/ppc/register.py b/pypy/jit/backend/ppc/register.py
--- a/pypy/jit/backend/ppc/register.py
+++ b/pypy/jit/backend/ppc/register.py
@@ -19,7 +19,7 @@
NONVOLATILES_FLOAT = [f14, f15, f16, f17, f18, f19, f20, f21, f22, f23,
f24, f25, f26, f27, f28, f29, f30, f31]
-
+VOLATILES_FLOAT = [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13]
SCRATCH = r0
SP = r1
@@ -33,6 +33,7 @@
r27, r28, r29, r30]
PARAM_REGS = [r3, r4, r5, r6, r7, r8, r9, r10]
+PARAM_FPREGS = [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13]
def get_managed_reg_index(reg):
if reg > r13.value:
diff --git a/pypy/jit/backend/ppc/runner.py b/pypy/jit/backend/ppc/runner.py
--- a/pypy/jit/backend/ppc/runner.py
+++ b/pypy/jit/backend/ppc/runner.py
@@ -27,7 +27,7 @@
translate_support_code, gcdescr)
# floats are not supported yet
- self.supports_floats = False
+ self.supports_floats = True
def setup(self):
self.asm = AssemblerPPC(self)
More information about the pypy-commit
mailing list