def b_offset(self, reladdr): offset = reladdr - self.get_relative_pos() if -2 ** 15 <= offset <= 2 ** 15 - 1: self.BRC(c.ANY, l.imm(offset)) else: # we have big loops! self.BRCL(c.ANY, l.imm(offset))
def emit_vec_float_neg(self, op, arglocs, regalloc): resloc, argloc, sizeloc = arglocs size = sizeloc.value if size == 8: self.mc.VFPSO(resloc, argloc, l.imm(3), l.imm(0), l.imm(0)) return not_implemented("vec_float_abs of size %d" % size)
def test_complement(self): self.a.mc.load_imm(r.r2, 0) #self.a.mc.LCGR(r.r2, r.r2) self.a.mc.XIHF(r.r2, loc.imm(0xffffFFFF)) self.a.mc.XILF(r.r2, loc.imm(0xffffFFFF)) self.a.mc.BCR(con.ANY, r.r14) assert run_asm(self.a) == -1
def test_and_imm(self): self.a.mc.NIHH(r.r2, loc.imm(0)) self.a.mc.NIHL(r.r2, loc.imm(0)) self.a.mc.NILL(r.r2, loc.imm(0)) self.a.mc.NILH(r.r2, loc.imm(0)) self.a.jmpto(r.r14) assert run_asm(self.a) == 0
def prepare_vec_int_signext(self, op): assert isinstance(op, VectorOp) a0 = op.getarg(0) assert isinstance(a0, VectorOp) loc0 = self.ensure_vector_reg(a0) resloc = self.force_allocate_vector_reg(op) return [resloc, loc0, imm(a0.bytesize), imm(op.bytesize)]
def test_or_imm(self): self.a.mc.OIHH(r.r2, loc.imm(0xffff)) self.a.mc.OIHL(r.r2, loc.imm(0xffff)) self.a.mc.OILL(r.r2, loc.imm(0xffff)) self.a.mc.OILH(r.r2, loc.imm(0xffff)) self.a.jmpto(r.r14) assert run_asm(self.a) == -1
def prepare_vec_unpack_i(self, op): assert isinstance(op, VectorOp) index = op.getarg(1) count = op.getarg(2) assert isinstance(index, ConstInt) assert isinstance(count, ConstInt) arg = op.getarg(0) if arg.is_vector(): srcloc = self.ensure_vector_reg(arg) assert isinstance(arg, VectorOp) size = arg.bytesize else: # unpack srcloc = self.ensure_reg(arg) size = WORD if op.is_vector(): resloc = self.force_allocate_vector_reg(op) else: resloc = self.force_allocate_reg(op) return [ resloc, srcloc, srcloc, imm(0), imm(index.value), imm(count.value), imm(size) ]
def b_offset(self, reladdr): offset = reladdr - self.get_relative_pos() if -2**15 <= offset <= 2**15 - 1: self.BRC(c.ANY, l.imm(offset)) else: # we have big loops! self.BRCL(c.ANY, l.imm(offset))
def emit_vec_float_sub(self, op, arglocs, regalloc): resloc, loc0, loc1, itemsize_loc = arglocs itemsize = itemsize_loc.value if itemsize == 8: self.mc.VFS(resloc, loc0, loc1, l.imm(3), l.imm(0), l.imm(0)) return not_implemented("vec_float_sub of size %d" % itemsize)
def prepare_vec_unpack_f(self, op): index = op.getarg(1) count = op.getarg(2) assert isinstance(index, ConstInt) assert isinstance(count, ConstInt) srcloc = self.ensure_vector_reg(op.getarg(0)) resloc = self.force_allocate_reg(op) return [resloc, srcloc, imm(index.value), imm(count.value)]
def test_or_bitpos_0to15(self): self.a.mc.XGR(r.r2, r.r2) self.a.mc.OIHH(r.r2, loc.imm(0x0000)) self.a.mc.OIHL(r.r2, loc.imm(0x0000)) self.a.mc.OILL(r.r2, loc.imm(0x0000)) self.a.mc.OILH(r.r2, loc.imm(0x300c)) self.a.jmpto(r.r14) res = run_asm(self.a) assert res == 0x00000000300c0000
def test_uint_rshift(self): self.a.mc.XGR(r.r4, r.r4) self.a.mc.LGFI(r.r5, loc.imm(63)) self.a.mc.NGR(r.r4, r.r5) self.a.mc.LGFI(r.r3, loc.imm(18)) self.a.mc.LGFI(r.r2, loc.imm(-1)) self.a.mc.SRLG(r.r2, r.r3, loc.addr(18)) self.a.jmpto(r.r14) assert run_asm(self.a) == 0
def test_simple_loop(self): self.a.mc.LGHI(r.r3, loc.imm(2**15 - 1)) self.a.mc.LGHI(r.r4, loc.imm(1)) L1 = self.a.mc.get_relative_pos() self.a.mc.SGR(r.r3, r.r4) LJ = self.a.mc.get_relative_pos() self.a.mc.BRCL(con.GT, loc.imm(L1 - LJ)) self.a.mc.LGR(r.r2, r.r3) self.a.jmpto(r.r14) assert run_asm(self.a) == 0
def test_ag_overflow(self): self.a.mc.BRC(con.ANY, loc.imm(4 + 8 + 8)) self.a.mc.write('\x7f' + '\xff' * 7) self.a.mc.write('\x7f' + '\xff' * 7) self.a.mc.LARL(r.r5, loc.imm(-8)) self.a.mc.LG(r.r4, loc.addr(8, r.r5)) self.a.mc.AG(r.r4, loc.addr(0, r.r5)) self.a.mc.LGR(r.r2, r.r4) self.a.jmpto(r.r14) assert run_asm(self.a) == -2
def emit_vec_float_eq(self, op, arglocs, regalloc): assert isinstance(op, VectorOp) resloc, loc0, loc1, sizeloc = arglocs size = sizeloc.value if size == 8: # bit 3 in last argument sets the condition code self.mc.VFCE(resloc, loc0, loc1, l.imm(3), l.imm(0), l.imm(1)) else: not_implemented("[zarch/assembler] float == for size %d" % size) flush_vec_cc(self, regalloc, c.VEQI, op.bytesize, resloc)
def test_ag_overflow(self): self.a.mc.BRC(con.ANY, loc.imm(4+8+8)) self.a.mc.write('\x7f' + '\xff' * 7) self.a.mc.write('\x7f' + '\xff' * 7) self.a.mc.LARL(r.r5, loc.imm(-8)) self.a.mc.LG(r.r4, loc.addr(8,r.r5)) self.a.mc.AG(r.r4, loc.addr(0,r.r5)) self.a.mc.LGR(r.r2, r.r4) self.a.jmpto(r.r14) assert run_asm(self.a) == -2
def test_simple_loop(self): self.a.mc.LGHI(r.r3, loc.imm(2**15-1)) self.a.mc.LGHI(r.r4, loc.imm(1)) L1 = self.a.mc.get_relative_pos() self.a.mc.SGR(r.r3, r.r4) LJ = self.a.mc.get_relative_pos() self.a.mc.BRCL(con.GT, loc.imm(L1-LJ)) self.a.mc.LGR(r.r2, r.r3) self.a.jmpto(r.r14) assert run_asm(self.a) == 0
def load_imm(self, dest_reg, word): if -2 ** 15 <= word <= 2 ** 15 - 1: self.LGHI(dest_reg, l.imm(word)) elif -2 ** 31 <= word <= 2 ** 31 - 1: self.LGFI(dest_reg, l.imm(word)) else: if self.pool and self.pool.contains_constant(word): self.LG(dest_reg, l.pool(self.pool.get_direct_offset(word))) return self.IILF(dest_reg, l.imm(word & 0xFFFFFFFF)) self.IIHF(dest_reg, l.imm((word >> 32) & 0xFFFFFFFF))
def prepare_cmp_op(self, op): a0 = op.getarg(0) a1 = op.getarg(1) invert = imm(0) l0 = self.ensure_reg(a0) if signed and check_imm32(a1): l1 = imm(a1.getint()) else: l1 = self.ensure_reg(a1) res = self.force_allocate_reg_or_cc(op) return [l0, l1, res, invert]
def load_imm(self, dest_reg, word): if -2**15 <= word <= 2**15 - 1: self.LGHI(dest_reg, l.imm(word)) elif -2**31 <= word <= 2**31 - 1: self.LGFI(dest_reg, l.imm(word)) else: if self.pool and self.pool.contains_constant(word): self.LG(dest_reg, l.pool(self.pool.get_direct_offset(word))) return self.IILF(dest_reg, l.imm(word & 0xFFFFffff)) self.IIHF(dest_reg, l.imm((word >> 32) & 0xFFFFffff))
def test_float_cmp(self): with ActivationRecordCtx(self): with LiteralPoolCtx(self) as pool: pool.float(1.0) pool.float(2.0) self.mc.LD(r.f0, loc.addr(0, r.r13)) self.mc.LD(r.f1, loc.addr(8, r.r13)) self.mc.CDBR(r.f0, r.f1) self.mc.LGHI(r.r2, loc.imm(0)) self.mc.BCR(con.EQ, r.r14) # must not branch self.mc.LGHI(r.r2, loc.imm(1)) self.a.jmpto(r.r14) assert run_asm(self.a) == 1
def prepare_finish(self, op): descr = op.getdescr() fail_descr = cast_instance_to_gcref(descr) # we know it does not move, but well rgc._make_sure_does_not_move(fail_descr) fail_descr = rffi.cast(lltype.Signed, fail_descr) assert fail_descr > 0 if op.numargs() > 0: loc = self.ensure_reg(op.getarg(0)) locs = [loc, imm(fail_descr)] else: locs = [imm(fail_descr)] return locs
def emit_guard_no_exception(self, op, arglocs, regalloc): self.mc.load_imm(r.SCRATCH, self.cpu.pos_exception()) self.mc.LG(r.SCRATCH2, l.addr(0,r.SCRATCH)) self.mc.cmp_op(r.SCRATCH2, l.imm(0), imm=True) self.guard_success_cc = c.EQ self._emit_guard(op, arglocs) # If the previous operation was a COND_CALL, overwrite its conditional # jump to jump over this GUARD_NO_EXCEPTION as well, if we can if self._find_nearby_operation(regalloc,-1).getopnum() == rop.COND_CALL: jmp_adr, fcond = self.previous_cond_call_jcond relative_target = self.mc.currpos() - jmp_adr pmc = OverwritingBuilder(self.mc, jmp_adr, 1) pmc.BRCL(fcond, l.imm(relative_target)) pmc.overwrite()
def test_printf(self): with ActivationRecordCtx(self): with self.label('lit'): self.mc.BRAS(r.r13, loc.imm(0)) for c in "hello syscall\n": self.mc.writechar(c) self.jump_here(self.mc.BRAS, 'lit') self.mc.LGHI(r.r2, loc.imm(1)) # stderr self.mc.LA(r.r3, loc.addr(0, r.r13)) # char* self.mc.LGHI(r.r4, loc.imm(14)) # length # write sys call self.mc.SVC(loc.imm(4)) self.a.jmpto(r.r14) assert run_asm(self.a) == 14
def _prepare_load(self, op): descr = op.getdescr() assert isinstance(descr, ArrayDescr) assert not descr.is_array_of_pointers() and \ not descr.is_array_of_structs() itemsize, ofs, _ = unpack_arraydescr(descr) integer = not (descr.is_array_of_floats() or descr.getconcrete_type() == FLOAT) a0 = op.getarg(0) a1 = op.getarg(1) base_loc = self.ensure_reg(a0) ofs_loc = self.ensure_reg(a1) result_loc = self.force_allocate_vector_reg(op) return [result_loc, base_loc, ofs_loc, imm(itemsize), imm(ofs), imm(integer)]
def test_simple_func(self): # enter self.a.mc.STMG(r.r11, r.r15, loc.addr(-96, r.SP)) self.a.mc.AHI(r.SP, loc.imm(-96)) # from the start of BRASL to end of jmpto there are 8+6 bytes self.a.mc.BRASL(r.r14, loc.imm(8 + 6)) self.a.mc.LMG(r.r11, r.r15, loc.addr(0, r.SP)) self.a.jmpto(r.r14) addr = self.a.mc.get_relative_pos() assert addr & 0x1 == 0 gen_func_prolog(self.a.mc) self.a.mc.LGHI(r.r2, loc.imm(321)) gen_func_epilog(self.a.mc) assert run_asm(self.a) == 321
def emit_guard_no_exception(self, op, arglocs, regalloc): self.mc.load_imm(r.SCRATCH, self.cpu.pos_exception()) self.mc.LG(r.SCRATCH2, l.addr(0, r.SCRATCH)) self.mc.cmp_op(r.SCRATCH2, l.imm(0), imm=True) self.guard_success_cc = c.EQ self._emit_guard(op, arglocs) # If the previous operation was a COND_CALL, overwrite its conditional # jump to jump over this GUARD_NO_EXCEPTION as well, if we can if self._find_nearby_operation(regalloc, -1).getopnum() == rop.COND_CALL: jmp_adr, fcond = self.previous_cond_call_jcond relative_target = self.mc.currpos() - jmp_adr pmc = OverwritingBuilder(self.mc, jmp_adr, 1) pmc.BRCL(fcond, l.imm(relative_target)) pmc.overwrite()
def emit_guard_nonnull_class(self, op, arglocs, regalloc): self.mc.cmp_op(arglocs[0], l.imm(1), imm=True, signed=False) patch_pos = self.mc.currpos() self.mc.reserve_cond_jump(short=True) self._cmp_guard_class(op, arglocs, regalloc) #self.mc.CGRT(r.SCRATCH, r.SCRATCH2, c.NE) pmc = OverwritingBuilder(self.mc, patch_pos, 1) pmc.BRC(c.LT, l.imm(self.mc.currpos() - patch_pos)) pmc.overwrite() self.guard_success_cc = c.EQ self._emit_guard(op, arglocs[2:])
def test_simple_func(self): # enter self.a.mc.STMG(r.r11, r.r15, loc.addr(-96, r.SP)) self.a.mc.AHI(r.SP, loc.imm(-96)) # from the start of BRASL to end of jmpto there are 8+6 bytes self.a.mc.BRASL(r.r14, loc.imm(8+6)) self.a.mc.LMG(r.r11, r.r15, loc.addr(0, r.SP)) self.a.jmpto(r.r14) addr = self.a.mc.get_relative_pos() assert addr & 0x1 == 0 gen_func_prolog(self.a.mc) self.a.mc.LGHI(r.r2, loc.imm(321)) gen_func_epilog(self.a.mc) assert run_asm(self.a) == 321
def prepare_gc_store_indexed(self, op): args = op.getarglist() base_loc = self.ensure_reg(op.getarg(0)) index_loc = self.ensure_reg_or_20bit_imm(op.getarg(1)) value_loc = self.ensure_reg(op.getarg(2)) scale_box = op.getarg(3) offset_box = op.getarg(4) size_box = op.getarg(5) assert isinstance(scale_box, ConstInt) assert isinstance(offset_box, ConstInt) assert isinstance(size_box, ConstInt) factor = scale_box.value assert factor == 1 offset = offset_box.value size = size_box.value return [base_loc, index_loc, value_loc, imm(offset), imm(abs(size))]
def emit_vec_int_ne(self, op, arglocs, regalloc): assert isinstance(op, VectorOp) resloc, loc0, loc1, sizeloc = arglocs size = sizeloc.value self.mc.VCEQ(resloc, loc0, loc1, l.itemsize_to_mask(size), l.imm(1)) self.mc.VNO(resloc, resloc, resloc) flush_vec_cc(self, regalloc, c.VNEI, op.bytesize, resloc)
def test_align(self, p, v): WORD = 8 self.a.mc.load_imm(r.r2, p) self.a.mc.LGHI(r.r0, loc.imm(~(WORD - 1))) self.a.mc.NGR(r.r2, r.r0) self.a.mc.BCR(con.ANY, r.r14) assert run_asm(self.a) == v
def prepare_vec_int_is_true(self, op): assert isinstance(op, VectorOp) arg = op.getarg(0) assert isinstance(arg, VectorOp) argloc = self.ensure_vector_reg(arg) resloc = self.force_allocate_vector_reg_or_cc(op) return [resloc, argloc, imm(arg.bytesize)]
def ensure_reg_or_any_imm(self, box): if box.type == FLOAT: return self.fprm.ensure_reg(box) else: if isinstance(box, Const): return imm(box.getint()) return self.rm.ensure_reg(box)
def test_literal_pool(self): gen_func_prolog(self.a.mc) self.a.mc.BRAS(r.r13, loc.imm(8 + self.mc.BRAS_byte_count)) self.a.mc.write('\x08\x07\x06\x05\x04\x03\x02\x01') self.a.mc.LG(r.r2, loc.addr(0, r.r13)) gen_func_epilog(self.a.mc) assert run_asm(self.a) == 0x0807060504030201
def emit_zero_array(self, op, arglocs, regalloc): base_loc, startindex_loc, length_loc, \ ofs_loc, itemsize_loc = arglocs if ofs_loc.is_imm(): assert check_imm_value(ofs_loc.value) self.mc.AGHI(base_loc, ofs_loc) else: self.mc.AGR(base_loc, ofs_loc) if startindex_loc.is_imm(): assert check_imm_value(startindex_loc.value) self.mc.AGHI(base_loc, startindex_loc) else: self.mc.AGR(base_loc, startindex_loc) assert not length_loc.is_imm() # contents of r0 do not matter because r1 is zero, so # no copying takes place self.mc.XGR(r.r1, r.r1) assert base_loc.is_even() assert length_loc.value == base_loc.value + 1 # s390x has memset directly as a hardware instruction!! # it needs 5 registers allocated # dst = rX, dst len = rX+1 (ensured by the regalloc) # src = r0, src len = r1 self.mc.MVCLE(base_loc, r.r0, l.addr(0)) # NOTE this instruction can (determined by the cpu), just # quit the movement any time, thus it is looped until all bytes # are copied! self.mc.BRC(c.OF, l.imm(-self.mc.MVCLE_byte_count))
def ensure_reg_or_20bit_imm(self, box): if box.type == FLOAT: return self.fprm.ensure_reg(box) else: if helper.check_imm20(box): return imm(box.getint()) return self.rm.ensure_reg(box)
def prepare_vec_pack_i(self, op): # new_res = vec_pack_i(res, src, index, count) assert isinstance(op, VectorOp) arg = op.getarg(1) index = op.getarg(2) count = op.getarg(3) assert isinstance(index, ConstInt) assert isinstance(count, ConstInt) arg0 = op.getarg(0) assert isinstance(arg0, VectorOp) vloc = self.ensure_vector_reg(arg0) srcloc = self.ensure_reg(arg) resloc = self.force_allocate_vector_reg(op) residx = index.value # where to put it in result? srcidx = 0 return [resloc, vloc, srcloc, imm(residx), imm(srcidx), imm(count.value), imm(arg0.bytesize)]
def test_align(self, p, v): WORD = 8 self.a.mc.load_imm(r.r2, p) self.a.mc.LGHI(r.r0, loc.imm(~(WORD-1))) self.a.mc.NGR(r.r2, r.r0) self.a.mc.BCR(con.ANY, r.r14) assert run_asm(self.a) == v
def prepare_vec_arith_unary(self, op): assert isinstance(op, VectorOp) a0 = op.getarg(0) loc0 = self.ensure_vector_reg(a0) resloc = self.force_allocate_vector_reg(op) sizeloc = imm(op.bytesize) return [resloc, loc0, sizeloc]