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) _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit