Esempio n. 1
0
class FloatOpAssembler(object):
    _mixin_ = True

    emit_float_add = gen_emit_rr_rp('ADBR', 'ADB')
    emit_float_sub = gen_emit_rr_rp('SDBR', 'SDB')
    emit_float_mul = gen_emit_rr_rp('MDBR', 'MDB')
    emit_float_truediv = gen_emit_rr_rp('DDBR', 'DDB')

    # Support for NaNs: S390X sets condition code to 0x3 (unordered)
    # whenever any operand is nan.
    # in the case float_le,float_ge the overflow bit is not set of
    # the initial condition!
    # e.g. guard_true(nan <= x): jumps 1100 inv => 0011, bit 3 set
    # e.g. guard_false(nan <= x): does not jump 1100, bit 3 not set
    # e.g. guard_true(nan >= nan): jumps 1010 inv => 0101, bit 3 set
    emit_float_lt = gen_emit_cmp_op(c.LT, fp=True)
    emit_float_le = gen_emit_cmp_op(c.FLE, fp=True)
    emit_float_eq = gen_emit_cmp_op(c.EQ, fp=True)
    emit_float_ne = gen_emit_cmp_op(c.NE, fp=True)
    emit_float_gt = gen_emit_cmp_op(c.GT, fp=True)
    emit_float_ge = gen_emit_cmp_op(c.FGE, fp=True)

    def emit_float_neg(self, op, arglocs, regalloc):
        l0, = arglocs
        self.mc.LCDBR(l0, l0)

    def emit_float_abs(self, op, arglocs, regalloc):
        l0, = arglocs
        self.mc.LPDBR(l0, l0)

    def emit_cast_float_to_int(self, op, arglocs, regalloc):
        f0, r0 = arglocs
        self.mc.CGDBR(r0, c.FP_TOWARDS_ZERO, f0)

    def emit_cast_int_to_float(self, op, arglocs, regalloc):
        r0, f0 = arglocs
        self.mc.CDGBR(f0, r0)

    def emit_convert_float_bytes_to_longlong(self, op, arglocs, regalloc):
        l0, res = arglocs
        self.mc.LGDR(res, l0)

    def emit_convert_longlong_bytes_to_float(self, op, arglocs, regalloc):
        l0, res = arglocs
        self.mc.LDGR(res, l0)
Esempio n. 2
0
class IntOpAssembler(object):
    _mixin_ = True

    emit_int_add = gen_emit_rr_rh_ri_rp('AGR', 'AGHI', 'AGFI', 'AG')
    emit_int_add_ovf = emit_int_add

    emit_nursery_ptr_increment = emit_int_add

    def emit_int_sub(self, op, arglocs, regalloc):
        res, l0, l1 = arglocs
        self.mc.SGRK(res, l0, l1)

    emit_int_sub_ovf = emit_int_sub

    emit_int_mul = gen_emit_rr_rh_ri_rp('MSGR', 'MGHI', 'MSGFI', 'MSG')

    def emit_int_mul_ovf(self, op, arglocs, regalloc):
        lr, lq, l1 = arglocs
        if l1.is_in_pool():
            self.mc.LG(r.SCRATCH, l1)
            l1 = r.SCRATCH
        elif l1.is_imm():
            self.mc.LGFI(r.SCRATCH, l1)
            l1 = r.SCRATCH
        else:
            # we are not allowed to modify l1 if it is not a scratch
            # register, thus copy it here!
            self.mc.LGR(r.SCRATCH, l1)
            l1 = r.SCRATCH

        mc = self.mc

        # check left neg
        jmp_lq_lt_0 = mc.get_relative_pos()
        mc.reserve_cond_jump()  # CGIJ lq < 0 +-----------+
        jmp_l1_ge_0 = mc.get_relative_pos()  #            |
        mc.reserve_cond_jump()  # CGIJ l1 >= 0 -----------|-> (both same sign)
        jmp_lq_pos_l1_neg = mc.get_relative_pos()  #      |
        mc.reserve_cond_jump(short=True)  #  BCR any -----|-> (xor negative)
        jmp_l1_neg_lq_neg = mc.get_relative_pos()  #      |
        mc.reserve_cond_jump()  # <-----------------------+
        # CGIJ l1 < 0 -> (both same_sign)
        # (xor negative)
        label_xor_neg = mc.get_relative_pos()
        mc.LPGR(lq, lq)
        mc.LPGR(l1, l1)
        mc.MLGR(lr, l1)
        mc.LGHI(r.SCRATCH, l.imm(-1))
        mc.RISBG(r.SCRATCH, r.SCRATCH, l.imm(0), l.imm(0x80 | 0), l.imm(0))
        # is the value greater than 2**63 ? then an overflow occured
        jmp_xor_lq_overflow = mc.get_relative_pos()
        mc.reserve_cond_jump()  # CLGRJ lq > 0x8000 ... 00 -> (label_overflow)
        jmp_xor_lr_overflow = mc.get_relative_pos()
        mc.reserve_cond_jump()  # CLGIJ lr > 0 -> (label_overflow)
        mc.LCGR(lq, lq)  # complement the value
        mc.XGR(r.SCRATCH, r.SCRATCH)
        mc.SPM(r.SCRATCH
               )  # 0x80 ... 00 clears the condition code and program mask
        jmp_no_overflow_xor_neg = mc.get_relative_pos()
        mc.reserve_cond_jump(short=True)

        # both are positive/negative
        label_both_same_sign = mc.get_relative_pos()
        mc.LPGR(lq, lq)
        mc.LPGR(l1, l1)
        mc.MLGR(lr, l1)
        mc.LGHI(r.SCRATCH, l.imm(-1))
        # 0xff -> shift 0 -> 0xff set MSB on pos 0 to zero -> 7f
        mc.RISBG(r.SCRATCH, r.SCRATCH, l.imm(1), l.imm(0x80 | 63), l.imm(0))
        jmp_lq_overflow = mc.get_relative_pos()
        mc.reserve_cond_jump()  # CLGRJ lq > 0x7fff ... ff -> (label_overflow)
        jmp_lr_overflow = mc.get_relative_pos()
        mc.reserve_cond_jump()  # CLGIJ lr > 0 -> (label_overflow)
        jmp_neither_lqlr_overflow = mc.get_relative_pos()
        mc.reserve_cond_jump(short=True)  # BRC any -> (label_end)

        # set overflow!
        label_overflow = mc.get_relative_pos()
        # set bit 34 & 35 -> indicates overflow
        mc.XGR(r.SCRATCH, r.SCRATCH)
        mc.OILH(r.SCRATCH, l.imm(0x3000))  # sets OF
        mc.SPM(r.SCRATCH)

        # no overflow happended
        label_end = mc.get_relative_pos()

        # patch patch patch!!!

        # jmp_lq_lt_0
        pos = jmp_lq_lt_0
        omc = OverwritingBuilder(self.mc, pos, 1)
        omc.CGIJ(lq, l.imm(0), c.LT, l.imm(jmp_l1_neg_lq_neg - pos))
        omc.overwrite()
        # jmp_l1_ge_0
        pos = jmp_l1_ge_0
        omc = OverwritingBuilder(self.mc, pos, 1)
        omc.CGIJ(l1, l.imm(0), c.GE, l.imm(label_both_same_sign - pos))
        omc.overwrite()
        # jmp_lq_pos_l1_neg
        pos = jmp_lq_pos_l1_neg
        omc = OverwritingBuilder(self.mc, pos, 1)
        omc.BRC(c.ANY, l.imm(label_xor_neg - pos))
        omc.overwrite()
        # jmp_l1_neg_lq_neg
        pos = jmp_l1_neg_lq_neg
        omc = OverwritingBuilder(self.mc, pos, 1)
        omc.CGIJ(l1, l.imm(0), c.LT, l.imm(label_both_same_sign - pos))
        omc.overwrite()

        # patch jmp_xor_lq_overflow
        pos = jmp_xor_lq_overflow
        omc = OverwritingBuilder(self.mc, pos, 1)
        omc.CLGRJ(lq, r.SCRATCH, c.GT, l.imm(label_overflow - pos))
        omc.overwrite()
        # patch jmp_xor_lr_overflow
        pos = jmp_xor_lr_overflow
        omc = OverwritingBuilder(self.mc, pos, 1)
        omc.CLGIJ(lr, l.imm(0), c.GT, l.imm(label_overflow - pos))
        omc.overwrite()
        # patch jmp_no_overflow_xor_neg
        omc = OverwritingBuilder(self.mc, jmp_no_overflow_xor_neg, 1)
        omc.BRC(c.ANY, l.imm(label_end - jmp_no_overflow_xor_neg))
        omc.overwrite()
        # patch jmp_lq_overflow
        omc = OverwritingBuilder(self.mc, jmp_lq_overflow, 1)
        omc.CLGRJ(lq, r.SCRATCH, c.GT, l.imm(label_overflow - jmp_lq_overflow))
        omc.overwrite()
        # patch jmp_lr_overflow
        omc = OverwritingBuilder(self.mc, jmp_lr_overflow, 1)
        omc.CLGIJ(lr, l.imm(0), c.GT, l.imm(label_overflow - jmp_lr_overflow))
        omc.overwrite()
        # patch jmp_neither_lqlr_overflow
        omc = OverwritingBuilder(self.mc, jmp_neither_lqlr_overflow, 1)
        omc.BRC(c.ANY, l.imm(label_end - jmp_neither_lqlr_overflow))
        omc.overwrite()

    emit_int_floordiv = gen_emit_div_mod('DSGR', 'DSG')
    emit_uint_floordiv = gen_emit_div_mod('DLGR', 'DLG')
    # NOTE division sets one register with the modulo value, thus
    # the regalloc ensures the right register survives.
    emit_int_mod = gen_emit_div_mod('DSGR', 'DSG')

    def emit_int_invert(self, op, arglocs, regalloc):
        l0, = arglocs
        assert not l0.is_imm()
        self.mc.LGHI(r.SCRATCH, l.imm(-1))
        self.mc.XGR(l0, r.SCRATCH)

    def emit_int_neg(self, op, arglocs, regalloc):
        l0, = arglocs
        self.mc.LCGR(l0, l0)

    def emit_int_signext(self, op, arglocs, regalloc):
        l0, = arglocs
        extend_from = op.getarg(1).getint()
        if extend_from == 1:
            self.mc.LGBR(l0, l0)
        elif extend_from == 2:
            self.mc.LGHR(l0, l0)
        elif extend_from == 4:
            self.mc.LGFR(l0, l0)
        else:
            raise AssertionError(extend_from)

    def emit_int_force_ge_zero(self, op, arglocs, resloc):
        l0, = arglocs
        off = self.mc.CGIJ_byte_count + self.mc.LGHI_byte_count
        self.mc.CGIJ(l0, l.imm(0), c.GE, l.imm(off))
        self.mc.LGHI(l0, l.imm(0))

    def emit_int_is_zero(self, op, arglocs, regalloc):
        l0, res = arglocs
        self.mc.CGHI(l0, l.imm(0))
        self.flush_cc(c.EQ, res)

    def emit_int_is_true(self, op, arglocs, regalloc):
        l0, res = arglocs
        self.mc.CGHI(l0, l.imm(0))
        self.flush_cc(c.NE, res)

    emit_int_and = gen_emit_rr_rp("NGR", "NG")
    emit_int_or = gen_emit_rr_rp("OGR", "OG")
    emit_int_xor = gen_emit_rr_rp("XGR", "XG")

    emit_int_rshift = gen_emit_shift("SRAG")
    emit_int_lshift = gen_emit_shift("SLLG")
    emit_uint_rshift = gen_emit_shift("SRLG")

    emit_int_le = gen_emit_cmp_op(c.LE)
    emit_int_lt = gen_emit_cmp_op(c.LT)
    emit_int_gt = gen_emit_cmp_op(c.GT)
    emit_int_ge = gen_emit_cmp_op(c.GE)
    emit_int_eq = gen_emit_cmp_op(c.EQ)
    emit_int_ne = gen_emit_cmp_op(c.NE)

    emit_ptr_eq = emit_int_eq
    emit_ptr_ne = emit_int_ne

    emit_instance_ptr_eq = emit_ptr_eq
    emit_instance_ptr_ne = emit_ptr_ne

    emit_uint_le = gen_emit_cmp_op(c.LE, signed=False)
    emit_uint_lt = gen_emit_cmp_op(c.LT, signed=False)
    emit_uint_gt = gen_emit_cmp_op(c.GT, signed=False)
    emit_uint_ge = gen_emit_cmp_op(c.GE, signed=False)