def _gen_address(self, result, base_loc, scaled_loc, scale=0, static_offset=0): assert scaled_loc.is_core_reg() assert base_loc.is_core_reg() assert check_imm_arg(scale) assert check_imm_arg(static_offset) if scale > 0: self.mc.LSL_ri(r.ip.value, scaled_loc.value, scale) scaled_loc = r.ip else: scaled_loc = scaled_loc self.mc.ADD_rr(result.value, base_loc.value, scaled_loc.value) self.mc.ADD_ri(result.value, result.value, static_offset)
def _adjust_sp(self, n): # adjust the current stack pointer by n bytes if n > 0: if check_imm_arg(n): self.mc.ADD_ri(r.sp.value, r.sp.value, n) else: self.mc.gen_load_int(r.ip.value, n) self.mc.ADD_rr(r.sp.value, r.sp.value, r.ip.value) elif n < 0: n = abs(n) if check_imm_arg(n): self.mc.SUB_ri(r.sp.value, r.sp.value, n) else: self.mc.gen_load_int(r.ip.value, n) self.mc.SUB_rr(r.sp.value, r.sp.value, r.ip.value)
def _call_assembler_load_result(self, op, result_loc): if op.result is not None: # load the return value from (tmploc, 0) kind = op.result.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.load_reg(self.mc, result_loc, r.r0, ofs=ofs) else: assert result_loc is r.r0 ofs = self.cpu.unpack_arraydescr(descr) assert check_imm_arg(ofs) self.mc.LDR_ri(result_loc.value, result_loc.value, imm=ofs)
def prepare_op_gc_store_indexed(self, op, fcond): boxes = op.getarglist() base_loc = self.make_sure_var_in_reg(boxes[0], boxes) value_loc = self.make_sure_var_in_reg(boxes[2], boxes) index_loc = self.make_sure_var_in_reg(boxes[1], boxes) assert boxes[3].getint() == 1 # scale ofs = boxes[4].getint() size = boxes[5].getint() assert check_imm_arg(ofs) return [value_loc, base_loc, index_loc, imm(size), imm(ofs)]
def _call_assembler_check_descr(self, value, tmploc): ofs = self.cpu.get_ofs_of_frame_field("jf_descr") self.mc.LDR_ri(r.ip.value, tmploc.value, imm=ofs) if check_imm_arg(value): self.mc.CMP_ri(r.ip.value, imm=value) else: self.mc.gen_load_int(r.lr.value, value) self.mc.CMP_rr(r.ip.value, r.lr.value) pos = self.mc.currpos() self.mc.BKPT() return pos
def _prepare_op_gc_load_indexed(self, op, fcond): boxes = op.getarglist() base_loc = self.make_sure_var_in_reg(boxes[0], boxes) index_loc = self.make_sure_var_in_reg(boxes[1], boxes) assert boxes[2].getint() == 1 # scale ofs = boxes[3].getint() nsize = boxes[4].getint() assert check_imm_arg(ofs) self.possibly_free_vars_for_op(op) self.free_temp_vars() res_loc = self.force_allocate_reg(op) return [res_loc, base_loc, index_loc, imm(nsize), imm(ofs)]
def prepare_op_gc_store(self, op, fcond): boxes = op.getarglist() base_loc = self.make_sure_var_in_reg(boxes[0], boxes) ofs = boxes[1].getint() value_loc = self.make_sure_var_in_reg(boxes[2], boxes) size = boxes[3].getint() ofs_size = default_imm_size if size < 8 else VMEM_imm_size if check_imm_arg(ofs, size=ofs_size): ofs_loc = imm(ofs) else: ofs_loc = self.get_scratch_reg(INT, boxes) self.assembler.load(ofs_loc, imm(ofs)) return [value_loc, base_loc, ofs_loc, imm(size)]
def _prepare_op_gc_load(self, op, fcond): a0 = op.getarg(0) ofs = op.getarg(1).getint() nsize = op.getarg(2).getint() # negative for "signed" base_loc = self.make_sure_var_in_reg(a0) immofs = imm(ofs) ofs_size = default_imm_size if abs(nsize) < 8 else VMEM_imm_size if check_imm_arg(ofs, size=ofs_size): ofs_loc = immofs else: ofs_loc = self.get_scratch_reg(INT, [a0]) self.assembler.load(ofs_loc, immofs) self.possibly_free_vars_for_op(op) self.free_temp_vars() res_loc = self.force_allocate_reg(op) return [base_loc, ofs_loc, res_loc, imm(nsize)]
def emit_op_zero_array(self, op, arglocs, regalloc, fcond): 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 fcond # nothing to do 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 = 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 = 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_box = TempVar() dstaddr_loc = regalloc.rm.force_allocate_reg(dstaddr_box, [args[2]]) 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, imm=ofs) else: self.mc.gen_load_int(r.ip.value, ofs) self.mc.ADD_rr(dstaddr_loc.value, reg, r.ip.value) # We use STRB, STRH 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 else: itemsize = 4 limit = itemsize next_group = -1 if itemsize < 4 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) & 3 limit = 4 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.ip.value, 0) i = 0 total_size = size_box.getint() while i < total_size: sz = itemsize if i == next_group: next_group += 4 if next_group <= total_size: sz = 4 if sz == 4: self.mc.STR_ri(r.ip.value, dstaddr_loc.value, imm=i) elif sz == 2: self.mc.STRH_ri(r.ip.value, dstaddr_loc.value, imm=i) else: self.mc.STRB_ri(r.ip.value, dstaddr_loc.value, imm=i) i += sz else: if isinstance(size_box, ConstInt): size_loc = imm(size_box.getint()) else: # load size_loc in a register different than dstaddr_loc size_loc = regalloc.rm.make_sure_var_in_reg(size_box, [dstaddr_box]) # # call memset() regalloc.before_call() self.simple_call_no_collect(imm(self.memset_addr), [dstaddr_loc, imm(0), size_loc]) regalloc.rm.possibly_free_var(size_box) regalloc.rm.possibly_free_var(dstaddr_box) return fcond