Beispiel #1
0
 def setup_method(self, method):
     cpu = CPU(None, None)
     self.a = AssemblerARM(cpu)
     self.a.setup_once()
     token = JitCellToken()
     clt = CompiledLoopToken(cpu, 0)
     clt.allgcrefs = []
     token.compiled_loop_token = clt
     self.a.setup(token)
Beispiel #2
0
 def setup(self):
     self.assembler = AssemblerARM(self, self.translate_support_code)
Beispiel #3
0
class AbstractARMCPU(AbstractLLCPU):

    IS_64_BIT = False

    supports_floats = True
    supports_longlong = True
    supports_singlefloats = True

    from rpython.jit.backend.arm.arch import JITFRAME_FIXED_SIZE
    all_reg_indexes = range(len(all_regs))
    gen_regs = all_regs
    float_regs = VFPRegisterManager.all_regs
    frame_reg = fp

    def __init__(self, rtyper, stats, opts=None, translate_support_code=False,
                 gcdescr=None):
        AbstractLLCPU.__init__(self, rtyper, stats, opts,
                               translate_support_code, gcdescr)
        self.cpuinfo = CPUInfo()

    def set_debug(self, flag):
        return self.assembler.set_debug(flag)

    def get_failargs_limit(self):
        if self.opts is not None:
            return self.opts.failargs_limit
        else:
            return 1000

    def setup(self):
        self.assembler = AssemblerARM(self, self.translate_support_code)

    def setup_once(self):
        self.cpuinfo.arch_version = detect_arch_version()
        self.cpuinfo.hf_abi = detect_hardfloat()
        #self.codemap.setup()
        self.assembler.setup_once()

    def finish_once(self):
        self.assembler.finish_once()

    def compile_bridge(self, faildescr, inputargs, operations,
                       original_loop_token, log=True, logger=None):
        clt = original_loop_token.compiled_loop_token
        clt.compiling_a_bridge()
        return self.assembler.assemble_bridge(logger, faildescr, inputargs,
                                              operations,
                                              original_loop_token, log=log)

    def clear_latest_values(self, count):
        setitem = self.assembler.fail_boxes_ptr.setitem
        null = lltype.nullptr(llmemory.GCREF.TO)
        for index in range(count):
            setitem(index, null)

    def cast_ptr_to_int(x):
        adr = llmemory.cast_ptr_to_adr(x)
        return CPU_ARM.cast_adr_to_int(adr)
    cast_ptr_to_int._annspecialcase_ = 'specialize:arglltype(0)'
    cast_ptr_to_int = staticmethod(cast_ptr_to_int)

    def redirect_call_assembler(self, oldlooptoken, newlooptoken):
        self.assembler.redirect_call_assembler(oldlooptoken, newlooptoken)

    def invalidate_loop(self, looptoken):
        """Activate all GUARD_NOT_INVALIDATED in the loop and its attached
        bridges.  Before this call, all GUARD_NOT_INVALIDATED do nothing;
        after this call, they all fail.  Note that afterwards, if one such
        guard fails often enough, it has a bridge attached to it; it is
        possible then to re-call invalidate_loop() on the same looptoken,
        which must invalidate all newer GUARD_NOT_INVALIDATED, but not the
        old one that already has a bridge attached to it."""
        from rpython.jit.backend.arm.codebuilder import InstrBuilder

        for jmp, tgt in looptoken.compiled_loop_token.invalidate_positions:
            mc = InstrBuilder(self.cpuinfo.arch_version)
            mc.B_offs(tgt)
            mc.copy_to_raw_memory(jmp)
        # positions invalidated
        looptoken.compiled_loop_token.invalidate_positions = []

    # should be combined with other ll backends
    def get_all_loop_runs(self):
        l = lltype.malloc(LOOP_RUN_CONTAINER,
                          len(self.assembler.loop_run_counters))
        for i, ll_s in enumerate(self.assembler.loop_run_counters):
            l[i].type = ll_s.type
            l[i].number = ll_s.number
            l[i].counter = ll_s.i
        return l

    def build_regalloc(self):
        ''' for tests'''
        from rpython.jit.backend.arm.regalloc import Regalloc
        assert self.assembler is not None
        return Regalloc(self.assembler)
Beispiel #4
0
 def setup(self):
     self.assembler = AssemblerARM(self, self.translate_support_code)
Beispiel #5
0
class AbstractARMCPU(AbstractLLCPU):

    IS_64_BIT = False

    supports_floats = True
    supports_longlong = True
    supports_singlefloats = True

    from rpython.jit.backend.arm.arch import JITFRAME_FIXED_SIZE
    all_reg_indexes = range(len(all_regs))
    gen_regs = all_regs
    float_regs = VFPRegisterManager.all_regs
    frame_reg = fp

    # can an ISA instruction handle a factor to the offset?
    # XXX should be: tuple(1 << i for i in range(31))
    load_supported_factors = (1, )

    def __init__(self,
                 rtyper,
                 stats,
                 opts=None,
                 translate_support_code=False,
                 gcdescr=None):
        AbstractLLCPU.__init__(self, rtyper, stats, opts,
                               translate_support_code, gcdescr)
        self.cpuinfo = CPUInfo()

    def set_debug(self, flag):
        return self.assembler.set_debug(flag)

    def setup(self):
        self.assembler = AssemblerARM(self, self.translate_support_code)

    def setup_once(self):
        self.cpuinfo.arch_version = detect_arch_version()
        self.cpuinfo.hf_abi = detect_hardfloat()
        self.cpuinfo.neon = detect_neon()
        #self.codemap.setup()
        self.assembler.setup_once()

    def finish_once(self):
        self.assembler.finish_once()

    def compile_bridge(self,
                       faildescr,
                       inputargs,
                       operations,
                       original_loop_token,
                       log=True,
                       logger=None):
        clt = original_loop_token.compiled_loop_token
        clt.compiling_a_bridge()
        return self.assembler.assemble_bridge(logger,
                                              faildescr,
                                              inputargs,
                                              operations,
                                              original_loop_token,
                                              log=log)

    def cast_ptr_to_int(x):
        adr = llmemory.cast_ptr_to_adr(x)
        return CPU_ARM.cast_adr_to_int(adr)

    cast_ptr_to_int._annspecialcase_ = 'specialize:arglltype(0)'
    cast_ptr_to_int = staticmethod(cast_ptr_to_int)

    def redirect_call_assembler(self, oldlooptoken, newlooptoken):
        self.assembler.redirect_call_assembler(oldlooptoken, newlooptoken)

    def invalidate_loop(self, looptoken):
        """Activate all GUARD_NOT_INVALIDATED in the loop and its attached
        bridges.  Before this call, all GUARD_NOT_INVALIDATED do nothing;
        after this call, they all fail.  Note that afterwards, if one such
        guard fails often enough, it has a bridge attached to it; it is
        possible then to re-call invalidate_loop() on the same looptoken,
        which must invalidate all newer GUARD_NOT_INVALIDATED, but not the
        old one that already has a bridge attached to it."""
        from rpython.jit.backend.arm.codebuilder import InstrBuilder

        for jmp, tgt in looptoken.compiled_loop_token.invalidate_positions:
            mc = InstrBuilder(self.cpuinfo.arch_version)
            mc.B_offs(tgt)
            mc.copy_to_raw_memory(jmp)
        # positions invalidated
        looptoken.compiled_loop_token.invalidate_positions = []

    # should be combined with other ll backends
    def get_all_loop_runs(self):
        l = lltype.malloc(LOOP_RUN_CONTAINER,
                          len(self.assembler.loop_run_counters))
        for i, ll_s in enumerate(self.assembler.loop_run_counters):
            l[i].type = ll_s.type
            l[i].number = ll_s.number
            l[i].counter = ll_s.i
        return l

    def build_regalloc(self):
        ''' for tests'''
        from rpython.jit.backend.arm.regalloc import Regalloc
        assert self.assembler is not None
        return Regalloc(self.assembler)
Beispiel #6
0
class TestRunningAssembler(object):
    def setup_method(self, method):
        cpu = CPU(None, None)
        self.a = AssemblerARM(cpu)
        self.a.setup_once()
        token = JitCellToken()
        clt = CompiledLoopToken(cpu, 0)
        clt.allgcrefs = []
        token.compiled_loop_token = clt
        self.a.setup(token)

    def test_make_operation_list(self):
        i = rop.INT_ADD
        from rpython.jit.backend.arm import assembler
        assert assembler.asm_operations[i] \
            is AssemblerARM.emit_op_int_add.im_func

    def test_load_small_int_to_reg(self):
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.r0.value, 123)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 123

    def test_load_medium_int_to_reg(self):
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.r0.value, 0xBBD7)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 48087

    def test_load_int_to_reg(self):
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.r0.value, 0xFFFFFF85)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == -123

    def test_load_neg_int_to_reg(self):
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.r0.value, -110)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == -110

    def test_load_neg_int_to_reg2(self):
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.r0.value, -3)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == -3

    def test_load_int1(self):
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.r0.value, 440)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 440

    def test_load_int2(self):
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.r0.value, 464)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 464

    def test_or(self):
        self.a.gen_func_prolog()
        self.a.mc.MOV_ri(r.r1.value, 8)
        self.a.mc.MOV_ri(r.r2.value, 8)
        self.a.mc.ORR_rr(r.r0.value, r.r1.value, r.r2.value, 4)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 0x88

    def test_sub(self):
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.r1.value, 123456)
        self.a.mc.SUB_ri(r.r0.value, r.r1.value, 123)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 123333

    def test_cmp(self):
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.r1.value, 22)
        self.a.mc.CMP_ri(r.r1.value, 123)
        self.a.mc.MOV_ri(r.r0.value, 1, c.LE)
        self.a.mc.MOV_ri(r.r0.value, 0, c.GT)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 1

    def test_int_le_false(self):
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.r1.value, 2222)
        self.a.mc.CMP_ri(r.r1.value, 123)
        self.a.mc.MOV_ri(r.r0.value, 1, c.LE)
        self.a.mc.MOV_ri(r.r0.value, 0, c.GT)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 0

    def test_simple_jump(self):
        self.a.gen_func_prolog()
        self.a.mc.MOV_ri(r.r1.value, 1)
        loop_head = self.a.mc.currpos()
        self.a.mc.CMP_ri(r.r1.value, 0)  # z=0, z=1
        self.a.mc.MOV_ri(r.r1.value, 0, cond=c.NE)
        self.a.mc.MOV_ri(r.r1.value, 7, cond=c.EQ)
        self.a.mc.B_offs(loop_head, c.NE)
        self.a.mc.MOV_rr(r.r0.value, r.r1.value)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 7

    def test_jump(self):
        self.a.gen_func_prolog()
        self.a.mc.MOV_ri(r.r1.value, 1)
        loop_head = self.a.mc.currpos()
        self.a.mc.ADD_ri(r.r1.value, r.r1.value, 1)
        self.a.mc.CMP_ri(r.r1.value, 9)
        self.a.mc.B_offs(loop_head, c.NE)
        self.a.mc.MOV_rr(r.r0.value, r.r1.value)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 9

    def test_B_offs_imm(self):
        self.a.mc.PUSH([reg.value for reg in r.callee_saved_registers])
        self.a.mc.MOV_ri(r.r0.value, 0)
        self.a.mc.MOV_ri(r.r1.value, 0)
        self.a.mc.CMP_rr(r.r0.value, r.r1.value)
        pos = self.a.mc.currpos()
        self.a.mc.MOV_ri(r.r0.value, 123, cond=c.NE)

        for x in range(15):
            self.a.mc.POP(
                [reg.value for reg in r.callee_restored_registers], cond=c.NE)

        self.a.mc.MOV_ri(r.r1.value, 33)
        self.a.mc.MOV_ri(r.r0.value, 23)
        self.a.mc.CMP_rr(r.r0.value, r.r1.value)
        self.a.mc.B_offs(pos)
        assert run_asm(self.a) == 123

    def test_B_offs_reg(self):
        self.a.mc.PUSH([reg.value for reg in r.callee_saved_registers])
        self.a.mc.MOV_ri(r.r0.value, 0)
        self.a.mc.MOV_ri(r.r1.value, 0)
        self.a.mc.CMP_rr(r.r0.value, r.r1.value)
        pos = self.a.mc.currpos()
        self.a.mc.MOV_ri(r.r0.value, 123, cond=c.NE)

        for x in range(100):
            self.a.mc.POP(
                [reg.value for reg in r.callee_restored_registers], cond=c.NE)

        self.a.mc.MOV_ri(r.r1.value, 33)
        self.a.mc.MOV_ri(r.r0.value, 23)
        self.a.mc.CMP_rr(r.r0.value, r.r1.value)
        self.a.mc.B_offs(pos)
        assert run_asm(self.a) == 123

    def test_call_python_func(self):
        functype = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed))
        call_addr = rffi.cast(lltype.Signed, llhelper(functype, callme))
        self.a.gen_func_prolog()
        self.a.mc.MOV_ri(r.r0.value, 123)
        self.a.mc.BL(call_addr)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 133

    def test_division(self):
        self.a.gen_func_prolog()
        self.a.mc.MOV_ri(r.r0.value, 123)
        self.a.mc.MOV_ri(r.r1.value, 2)

        # call to div
        self.a.mc.PUSH(range(2, 12))
        div_addr = rffi.cast(lltype.Signed, arm_int_div)
        self.a.mc.BL(div_addr)
        self.a.mc.POP(range(2, 12))
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 61

    def test_DIV(self):
        self.a.gen_func_prolog()
        self.a.mc.MOV_ri(r.r0.value, 123)
        self.a.mc.MOV_ri(r.r1.value, 2)
        self.a.mc.DIV()
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 61

    def test_DIV2(self):
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.r0.value, -110)
        self.a.mc.gen_load_int(r.r1.value, 3)
        self.a.mc.DIV()
        self.a.gen_func_epilog()
        assert run_asm(self.a) == -36

    def test_DIV3(self):
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.r8.value, 110)
        self.a.mc.gen_load_int(r.r9.value, -3)
        self.a.mc.MOV_rr(r.r0.value, r.r8.value)
        self.a.mc.MOV_rr(r.r1.value, r.r9.value)
        self.a.mc.DIV()
        self.a.gen_func_epilog()
        assert run_asm(self.a) == -36

    def test_bl_with_conditional_exec(self):
        functype = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed))
        call_addr = rffi.cast(lltype.Signed, llhelper(functype, callme))
        self.a.gen_func_prolog()
        self.a.mc.MOV_ri(r.r0.value, 123)
        self.a.mc.CMP_ri(r.r0.value, 1)
        self.a.mc.BL(call_addr, c.NE)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 133

    def test_mov_small_imm_loc_to_loc(self):
        self.a.gen_func_prolog()
        self.a.mov_loc_loc(imm(12), r.r0)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 12

    def test_mov_large_imm_loc_to_loc(self):
        self.a.gen_func_prolog()
        self.a.mov_loc_loc(imm(2478), r.r0)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == 2478

    def test_load_store(self):
        x = 0x60002224
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.r1.value, x)
        self.a.mc.SUB_ri(r.sp.value, r.sp.value, 8)
        self.a.mc.MOV_ri(r.r3.value, 8)
        self.a.mc.STR_rr(r.r1.value, r.sp.value, r.r3.value)
        self.a.mc.LDR_ri(r.r0.value, r.sp.value, 8)
        self.a.mc.ADD_ri(r.sp.value, r.sp.value, 8)
        self.a.gen_func_epilog()
        assert run_asm(self.a) == x
    
    def test_stm(self):
        container = lltype.malloc(lltype.Array(lltype.Signed, hints={'nolength': True}), 10, flavor='raw')
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, container))
        for x in range(10):
            self.a.mc.gen_load_int(x, x)
        self.a.mc.STM(r.ip.value, [x for x in range(10)])
        self.a.gen_func_epilog()
        run_asm(self.a)
        for x in range(10):
            assert container[x] == x
        lltype.free(container, flavor='raw')

    def test_ldm(self):
        container = lltype.malloc(lltype.Array(lltype.Signed, hints={'nolength': True}), 10, flavor='raw')
        for x in range(10):
            container[x] = x
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, container))
        self.a.mc.LDM(r.ip.value, [x for x in range(10)])
        for x in range(1, 10):
            self.a.mc.ADD_rr(0, 0, x)
        self.a.gen_func_epilog()
        res = run_asm(self.a)
        assert res == sum(range(10))
        lltype.free(container, flavor='raw')

    def test_vstm(self):
        n = 14
        source_container = lltype.malloc(lltype.Array(longlong.FLOATSTORAGE,
            hints={'nolength': True}), n, flavor='raw')
        target_container = lltype.malloc(lltype.Array(longlong.FLOATSTORAGE,
            hints={'nolength': True}), n, flavor='raw')
        for x in range(n):
            source_container[x] = longlong.getfloatstorage(float("%d.%d" % (x,x)))
        self.a.gen_func_prolog()
        for x in range(n):
            self.a.mc.ADD_ri(r.ip.value, r.ip.value, 8)
            self.a.mc.VLDR(n, r.ip.value)
        self.a.mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, target_container))
        self.a.mc.VSTM(r.ip.value, [x for x in range(n)])
        self.a.gen_func_epilog()
        run_asm(self.a)
        for d in range(n):
            res = longlong.getrealfloat(target_container[0]) == float("%d.%d" % (d,d))
        lltype.free(source_container, flavor='raw')
        lltype.free(target_container, flavor='raw')

    def test_vldm(self):
        n = 14
        container = lltype.malloc(lltype.Array(longlong.FLOATSTORAGE,
                                hints={'nolength': True}), n, flavor='raw')
        for x in range(n):
            container[x] = longlong.getfloatstorage(float("%d.%d" % (x,x)))
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, container))
        self.a.mc.VLDM(r.ip.value, [x for x in range(n)])
        for x in range(1, n):
            self.a.mc.VADD(0, 0, x)
        self.a.mc.VSTR(r.d0.value, r.ip.value)
        self.a.gen_func_epilog()
        res = run_asm(self.a)
        assert longlong.getrealfloat(container[0]) == sum([float("%d.%d" % (d,d)) for d in range(n)])
        lltype.free(container, flavor='raw')

    def test_vstm_vldm_combined(self):
        n = 14
        source_container = lltype.malloc(lltype.Array(longlong.FLOATSTORAGE,
            hints={'nolength': True}), n, flavor='raw')
        target_container = lltype.malloc(lltype.Array(longlong.FLOATSTORAGE,
            hints={'nolength': True}), n, flavor='raw')
        for x in range(n):
            source_container[x] = longlong.getfloatstorage(float("%d.%d" % (x,x)))
        self.a.gen_func_prolog()
        self.a.mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, source_container))
        self.a.mc.VLDM(r.ip.value, [x for x in range(n)])
        self.a.mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, target_container))
        self.a.mc.VSTM(r.ip.value, [x for x in range(n)])
        self.a.gen_func_epilog()
        run_asm(self.a)
        for d in range(n):
            res = longlong.getrealfloat(target_container[0]) == float("%d.%d" % (d,d))
        lltype.free(source_container, flavor='raw')
        lltype.free(target_container, flavor='raw')