예제 #1
0
 def _call_assembler_load_result(self, op, result_loc):
     if op.type != 'v':
         # load the return value from (tmploc, 0)
         kind = op.type
         descr = self.cpu.getarraydescr_for_frame(kind)
         if kind == FLOAT:
             ofs = self.cpu.unpack_arraydescr(descr)
             assert check_imm_arg(ofs)
             assert result_loc.is_vfp_reg()
             # we always have a register here, since we have to sync them
             # before call_assembler
             self.mc.LDR_di(result_loc.value, r.x0.value, ofs)
         else:
             assert result_loc is r.x0
             ofs = self.cpu.unpack_arraydescr(descr)
             assert check_imm_arg(ofs)
             self.mc.LDR_ri(result_loc.value, r.x0.value, ofs)
예제 #2
0
 def _call_assembler_check_descr(self, value, tmploc):
     ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
     self.mc.LDR_ri(r.ip0.value, tmploc.value, ofs)
     if check_imm_arg(value):
         self.mc.CMP_ri(r.ip0.value, value)
     else:
         self.mc.gen_load_int(r.ip1.value, value)
         self.mc.CMP_rr(r.ip0.value, r.ip1.value)
     pos = self.mc.currpos()
     self.mc.BRK()
     return pos
예제 #3
0
 def emit_op_gc_store_indexed(self, op, arglocs):
     value_loc, base_loc, index_loc, size_loc, ofs_loc = arglocs
     assert index_loc.is_core_reg()
     # add the base offset
     if ofs_loc.value != 0:
         if check_imm_arg(ofs_loc.value):
             self.mc.ADD_ri(r.ip0.value, index_loc.value, ofs_loc.value)
         else:
             # ofs_loc.value is too large for an ADD_ri
             self.load(r.ip0, ofs_loc)
             self.mc.ADD_rr(r.ip0.value, r.ip0.value, index_loc.value)
         index_loc = r.ip0
     scale = get_scale(size_loc.value)
     self._write_to_mem(value_loc, base_loc, index_loc, scale)
예제 #4
0
 def _emit_op_gc_load_indexed(self, op, arglocs):
     res_loc, base_loc, index_loc, nsize_loc, ofs_loc = arglocs
     assert index_loc.is_core_reg()
     nsize = nsize_loc.value
     signed = (nsize < 0)
     # add the base offset
     if ofs_loc.value != 0:
         if check_imm_arg(ofs_loc.value):
             self.mc.ADD_ri(r.ip0.value, index_loc.value, ofs_loc.value)
         else:
             # ofs_loc.value is too large for an ADD_ri
             self.load(r.ip0, ofs_loc)
             self.mc.ADD_rr(r.ip0.value, r.ip0.value, index_loc.value)
         index_loc = r.ip0
     #
     scale = get_scale(abs(nsize))
     self._load_from_mem(res_loc, base_loc, index_loc, scale, signed)
예제 #5
0
    def emit_op_zero_array(self, op, arglocs):
        from rpython.jit.backend.llsupport.descr import unpack_arraydescr
        assert len(arglocs) == 0
        size_box = op.getarg(2)
        if isinstance(size_box, ConstInt) and size_box.getint() == 0:
            return
        itemsize, baseofs, _ = unpack_arraydescr(op.getdescr())
        args = op.getarglist()
        #
        # ZERO_ARRAY(base_loc, start, size, 1, 1)
        # 'start' and 'size' are both expressed in bytes,
        # and the two scaling arguments should always be ConstInt(1) on ARM.
        assert args[3].getint() == 1
        assert args[4].getint() == 1
        #
        base_loc = self._regalloc.rm.make_sure_var_in_reg(args[0], args)
        startbyte_box = args[1]
        if isinstance(startbyte_box, ConstInt):
            startbyte_loc = None
            startbyte = startbyte_box.getint()
            assert startbyte >= 0
        else:
            startbyte_loc = self._regalloc.rm.make_sure_var_in_reg(startbyte_box,
                                                                   args)
            startbyte = -1

        # base_loc and startbyte_loc are in two regs here (or startbyte_loc
        # is an immediate).  Compute the dstaddr_loc, which is the raw
        # address that we will pass as first argument to memset().
        # It can be in the same register as either one, but not in
        # args[2], because we're still needing the latter.
        dstaddr_loc = r.ip1
        if startbyte >= 0:    # a constant
            ofs = baseofs + startbyte
            reg = base_loc.value
        else:
            self.mc.ADD_rr(dstaddr_loc.value,
                           base_loc.value, startbyte_loc.value)
            ofs = baseofs
            reg = dstaddr_loc.value
        if check_imm_arg(ofs):
            self.mc.ADD_ri(dstaddr_loc.value, reg, ofs)
        else:
            self.mc.gen_load_int(r.ip0.value, ofs)
            self.mc.ADD_rr(dstaddr_loc.value, reg, r.ip0.value)

        # We use STRB, STRH, STRW or STR based on whether we know the array
        # item size is a multiple of 1, 2 or 4.
        if   itemsize & 1: itemsize = 1
        elif itemsize & 2: itemsize = 2
        elif itemsize & 4: itemsize = 4
        else:              itemsize = 8
        limit = itemsize
        next_group = -1
        if itemsize < 8 and startbyte >= 0:
            # we optimize STRB/STRH into STR, but this needs care:
            # it only works if startindex_loc is a constant, otherwise
            # we'd be doing unaligned accesses.
            next_group = (-startbyte) & 7
            limit = 8

        if (isinstance(size_box, ConstInt) and
                size_box.getint() <= 14 * limit):     # same limit as GCC
            # Inline a series of STR operations, starting at 'dstaddr_loc'.
            #
            self.mc.gen_load_int(r.ip0.value, 0)
            i = 0
            adjustment = 0
            needs_adjustment = itemsize < 8 and (startbyte % 8)
            total_size = size_box.getint()
            while i < total_size:
                sz = itemsize
                if i == next_group:
                    next_group += 8
                    if next_group <= total_size:
                        sz = 8
                if sz == 8:
                    if needs_adjustment:
                        self.mc.ADD_ri(dstaddr_loc.value, dstaddr_loc.value, i)
                        adjustment = -i
                        needs_adjustment = False
                    self.mc.STR_ri(r.ip0.value, dstaddr_loc.value, i + adjustment)                    
                elif sz == 4:
                    self.mc.STRW_ri(r.ip0.value, dstaddr_loc.value, i + adjustment)
                elif sz == 2:
                    self.mc.STRH_ri(r.ip0.value, dstaddr_loc.value, i + adjustment)
                else:
                    self.mc.STRB_ri(r.ip0.value, dstaddr_loc.value, i + adjustment)
                i += sz

        else:
            if isinstance(size_box, ConstInt):
                size_loc = self.imm(size_box.getint())
            else:
                # load size_loc in a register different than dstaddr_loc
                size_loc = self._regalloc.rm.make_sure_var_in_reg(size_box,
                                                            [])
            #
            # call memset()
            self._regalloc.before_call()
            self.simple_call_no_collect(self.imm(self.memset_addr),
                                        [dstaddr_loc, self.imm(0), size_loc])
            self._regalloc.rm.possibly_free_var(size_box)