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)
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
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)
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)
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)