File: assembler.py

package info (click to toggle)
pypy 5.6.0%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 97,040 kB
  • ctags: 185,069
  • sloc: python: 1,147,862; ansic: 49,642; cpp: 5,245; asm: 5,169; makefile: 529; sh: 481; xml: 232; lisp: 45
file content (128 lines) | stat: -rw-r--r-- 4,253 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from __future__ import with_statement
from rpython.jit.backend.arm import conditions as c
from rpython.jit.backend.arm import registers as r
from rpython.jit.backend.arm.codebuilder import InstrBuilder
from rpython.jit.metainterp.history import FLOAT
from rpython.rlib.rarithmetic import r_uint, r_longlong, intmask
from rpython.jit.metainterp.resoperation import rop


def flush_cc(asm, condition, result_loc):
    # After emitting an instruction that leaves a boolean result in
    # a condition code (cc), call this.  In the common case, result_loc
    # will be set to 'fp' by the regalloc, which in this case means
    # "propagate it between this operation and the next guard by keeping
    # it in the cc".  In the uncommon case, result_loc is another
    # register, and we emit a load from the cc into this register.
    assert asm.guard_success_cc == c.cond_none
    if result_loc is r.fp:
        asm.guard_success_cc = condition
    else:
        asm.mc.MOV_ri(result_loc.value, 1, condition)
        asm.mc.MOV_ri(result_loc.value, 0, c.get_opposite_of(condition))


def gen_emit_op_unary_cmp(name, true_cond):
    def f(self, op, arglocs, regalloc, fcond):
        assert fcond is not None
        reg, res = arglocs
        self.mc.CMP_ri(reg.value, 0)
        flush_cc(self, true_cond, res)
        return fcond
    f.__name__ = 'emit_op_%s' % name
    return f

def gen_emit_op_ri(name, opname):
    ri_op = getattr(InstrBuilder, '%s_ri' % opname)
    rr_op = getattr(InstrBuilder, '%s_rr' % opname)
    def f(self, op, arglocs, regalloc, fcond):
        assert fcond is not None
        l0, l1, res = arglocs
        if l1.is_imm():
            ri_op(self.mc, res.value, l0.value, imm=l1.value, cond=fcond)
        else:
            rr_op(self.mc, res.value, l0.value, l1.value)
        return fcond
    f.__name__ = 'emit_op_%s' % name
    return f

def gen_emit_cmp_op(name, true_cond):
    def f(self, op, arglocs, regalloc, fcond):
        l0, l1, res = arglocs

        if l1.is_imm():
            self.mc.CMP_ri(l0.value, imm=l1.getint(), cond=fcond)
        else:
            self.mc.CMP_rr(l0.value, l1.value, cond=fcond)
        flush_cc(self, true_cond, res)
        return fcond
    f.__name__ = 'emit_op_%s' % name
    return f

def gen_emit_float_op(name, opname):
    op_rr = getattr(InstrBuilder, opname)
    def f(self, op, arglocs, regalloc, fcond):
        arg1, arg2, result = arglocs
        op_rr(self.mc, result.value, arg1.value, arg2.value)
        return fcond
    f.__name__ = 'emit_op_%s' % name
    return f

def gen_emit_unary_float_op(name, opname):
    op_rr = getattr(InstrBuilder, opname)
    def f(self, op, arglocs, regalloc, fcond):
        arg1, result = arglocs
        op_rr(self.mc, result.value, arg1.value)
        return fcond
    f.__name__ = 'emit_op_%s' % name
    return f

def gen_emit_float_cmp_op(name, true_cond):
    def f(self, op, arglocs, regalloc, fcond):
        arg1, arg2, res = arglocs
        self.mc.VCMP(arg1.value, arg2.value)
        self.mc.VMRS(cond=fcond)
        flush_cc(self, true_cond, res)
        return fcond
    f.__name__ = 'emit_op_%s' % name
    return f


class saved_registers(object):
    def __init__(self, cb, regs_to_save, vfp_regs_to_save=None):
        self.cb = cb
        if vfp_regs_to_save is None:
            vfp_regs_to_save = []
        self.regs = regs_to_save
        self.vfp_regs = vfp_regs_to_save

    def __enter__(self):
        if len(self.regs) > 0:
            self.cb.PUSH([r.value for r in self.regs])
        if len(self.vfp_regs) > 0:
            self.cb.VPUSH([r.value for r in self.vfp_regs])

    def __exit__(self, *args):
        if len(self.vfp_regs) > 0:
            self.cb.VPOP([r.value for r in self.vfp_regs])
        if len(self.regs) > 0:
            self.cb.POP([r.value for r in self.regs])

def count_reg_args(args):
    reg_args = 0
    words = 0
    count = 0
    for x in range(min(len(args), 4)):
        if args[x].type == FLOAT:
            words += 2
            if count % 2 != 0:
                words += 1
                count = 0
        else:
            count += 1
            words += 1
        reg_args += 1
        if words > 4:
            reg_args = x
            break
    return reg_args