Author: Maciej Fijalkowski <fij...@gmail.com> Branch: arm64 Changeset: r95784:b24d4ad8a3c6 Date: 2019-02-04 13:49 +0000 http://bitbucket.org/pypy/pypy/changeset/b24d4ad8a3c6/
Log: (arigo, fijal) Start building the scaffolding - passes STP encoding test diff --git a/rpython/jit/backend/aarch64/__init__.py b/rpython/jit/backend/aarch64/__init__.py new file mode 100644 diff --git a/rpython/jit/backend/aarch64/arch.py b/rpython/jit/backend/aarch64/arch.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/aarch64/arch.py @@ -0,0 +1,12 @@ + +WORD = 8 + +# The stack contains the force_index and the, callee saved registers and +# ABI required information +# All the rest of the data is in a GC-managed variable-size "frame". +# This jitframe object's address is always stored in the register FP +# A jitframe is a jit.backend.llsupport.llmodel.jitframe.JITFRAME +# Stack frame fixed area +# Currently only the force_index +JITFRAME_FIXED_SIZE = 12 + 8 +# 12 GPR + 8 VFP Regs diff --git a/rpython/jit/backend/aarch64/assembler.py b/rpython/jit/backend/aarch64/assembler.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/aarch64/assembler.py @@ -0,0 +1,192 @@ + +from rpython.jit.backend.aarch64.arch import WORD, JITFRAME_FIXED_SIZE +from rpython.jit.backend.aarch64.codebuilder import InstrBuilder +#from rpython.jit.backend.arm.locations import imm, StackLocation, get_fp_offset +#from rpython.jit.backend.arm.helper.regalloc import VMEM_imm_size +from rpython.jit.backend.aarch64.opassembler import ResOpAssembler +from rpython.jit.backend.aarch64.regalloc import Regalloc +# CoreRegisterManager, check_imm_arg, VFPRegisterManager, +# operations as regalloc_operations) +#from rpython.jit.backend.arm import callbuilder +from rpython.jit.backend.aarch64 import registers as r +from rpython.jit.backend.llsupport import jitframe +from rpython.jit.backend.llsupport.assembler import BaseAssembler +from rpython.jit.backend.llsupport.regalloc import get_scale, valid_addressing_size +from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper +from rpython.jit.backend.model import CompiledLoopToken +from rpython.jit.codewriter.effectinfo import EffectInfo +from rpython.jit.metainterp.history import AbstractFailDescr, FLOAT, INT, VOID +from rpython.jit.metainterp.resoperation import rop +from rpython.rlib.debug import debug_print, debug_start, debug_stop +from rpython.rlib.jit import AsmInfo +from rpython.rlib.objectmodel import we_are_translated, specialize, compute_unique_id +from rpython.rlib.rarithmetic import r_uint +from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref +from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rtyper.lltypesystem.lloperation import llop +from rpython.rlib.rjitlog import rjitlog as jl + +class AssemblerARM64(ResOpAssembler): + def assemble_loop(self, jd_id, unique_id, logger, loopname, inputargs, + operations, looptoken, log): + clt = CompiledLoopToken(self.cpu, looptoken.number) + looptoken.compiled_loop_token = clt + + if not we_are_translated(): + # Arguments should be unique + assert len(set(inputargs)) == len(inputargs) + + self.setup(looptoken) + + frame_info = self.datablockwrapper.malloc_aligned( + jitframe.JITFRAMEINFO_SIZE, alignment=WORD) + clt.frame_info = rffi.cast(jitframe.JITFRAMEINFOPTR, frame_info) + clt.frame_info.clear() # for now + + if log: + operations = self._inject_debugging_code(looptoken, operations, + 'e', looptoken.number) + + regalloc = Regalloc(assembler=self) + allgcrefs = [] + operations = regalloc.prepare_loop(inputargs, operations, looptoken, + allgcrefs) + self.reserve_gcref_table(allgcrefs) + functionpos = self.mc.get_relative_pos() + + self._call_header_with_stack_check() + self._check_frame_depth_debug(self.mc) + + loop_head = self.mc.get_relative_pos() + looptoken._ll_loop_code = loop_head + # + frame_depth_no_fixed_size = self._assemble(regalloc, inputargs, operations) + self.update_frame_depth(frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE) + # + size_excluding_failure_stuff = self.mc.get_relative_pos() + + self.write_pending_failure_recoveries() + + full_size = self.mc.get_relative_pos() + rawstart = self.materialize_loop(looptoken) + looptoken._ll_function_addr = rawstart + functionpos + + self.patch_gcref_table(looptoken, rawstart) + self.process_pending_guards(rawstart) + self.fixup_target_tokens(rawstart) + + if log and not we_are_translated(): + self.mc._dump_trace(rawstart, + 'loop.asm') + + ops_offset = self.mc.ops_offset + + if logger: + log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc) + log.write(inputargs, operations, ops_offset=ops_offset) + + # legacy + if logger.logger_ops: + logger.logger_ops.log_loop(inputargs, operations, 0, + "rewritten", name=loopname, + ops_offset=ops_offset) + + self.teardown() + + debug_start("jit-backend-addr") + debug_print("Loop %d (%s) has address 0x%x to 0x%x (bootstrap 0x%x)" % ( + looptoken.number, loopname, + r_uint(rawstart + loop_head), + r_uint(rawstart + size_excluding_failure_stuff), + r_uint(rawstart + functionpos))) + debug_print(" gc table: 0x%x" % r_uint(rawstart)) + debug_print(" function: 0x%x" % r_uint(rawstart + functionpos)) + debug_print(" resops: 0x%x" % r_uint(rawstart + loop_head)) + debug_print(" failures: 0x%x" % r_uint(rawstart + + size_excluding_failure_stuff)) + debug_print(" end: 0x%x" % r_uint(rawstart + full_size)) + debug_stop("jit-backend-addr") + + return AsmInfo(ops_offset, rawstart + loop_head, + size_excluding_failure_stuff - loop_head) + + def setup(self, looptoken): + BaseAssembler.setup(self, looptoken) + assert self.memcpy_addr != 0, 'setup_once() not called?' + if we_are_translated(): + self.debug = False + self.current_clt = looptoken.compiled_loop_token + self.mc = InstrBuilder() + self.pending_guards = [] + #assert self.datablockwrapper is None --- but obscure case + # possible, e.g. getting MemoryError and continuing + allblocks = self.get_asmmemmgr_blocks(looptoken) + self.datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr, + allblocks) + self.mc.datablockwrapper = self.datablockwrapper + self.target_tokens_currently_compiling = {} + self.frame_depth_to_patch = [] + + def _build_failure_recovery(self, exc, withfloats=False): + pass # XXX + + def _build_wb_slowpath(self, withcards, withfloats=False, for_frame=False): + pass # XXX + + def build_frame_realloc_slowpath(self): + pass + + def _build_propagate_exception_path(self): + pass + + def _build_cond_call_slowpath(self, supports_floats, callee_only): + pass + + def _build_stack_check_slowpath(self): + pass + + def reserve_gcref_table(self, allgcrefs): + pass + + def _call_header_with_stack_check(self): + self._call_header() + if self.stack_check_slowpath == 0: + pass # no stack check (e.g. not translated) + else: + endaddr, lengthaddr, _ = self.cpu.insert_stack_check() + # load stack end + self.mc.gen_load_int(r.ip.value, endaddr) # load ip, [end] + self.mc.LDR_ri(r.ip.value, r.ip.value) # LDR ip, ip + # load stack length + self.mc.gen_load_int(r.lr.value, lengthaddr) # load lr, lengh + self.mc.LDR_ri(r.lr.value, r.lr.value) # ldr lr, *lengh + # calculate ofs + self.mc.SUB_rr(r.ip.value, r.ip.value, r.sp.value) # SUB ip, current + # if ofs + self.mc.CMP_rr(r.ip.value, r.lr.value) # CMP ip, lr + self.mc.BL(self.stack_check_slowpath, c=c.HI) # call if ip > lr + + def _call_header(self): + stack_size = WORD #alignment + stack_size += len(r.callee_saved_registers) * WORD + if self.cpu.supports_floats: + stack_size += len(r.callee_saved_vfp_registers) * 2 * WORD + + # push all callee saved registers including lr; and push r1 as + # well, which contains the threadlocal_addr argument. Note that + # we're pushing a total of 10 words, which keeps the stack aligned. + self.mc.PUSH([reg.value for reg in r.callee_saved_registers] + + [r.r1.value]) + self.saved_threadlocal_addr = 0 # at offset 0 from location 'sp' + if self.cpu.supports_floats: + self.mc.VPUSH([reg.value for reg in r.callee_saved_vfp_registers]) + self.saved_threadlocal_addr += ( + len(r.callee_saved_vfp_registers) * 2 * WORD) + assert stack_size % 8 == 0 # ensure we keep alignment + + # set fp to point to the JITFRAME + self.mc.MOV_rr(r.fp.value, r.r0.value) + # + gcrootmap = self.cpu.gc_ll_descr.gcrootmap + if gcrootmap and gcrootmap.is_shadow_stack: + self.gen_shadowstack_header(gcrootmap) diff --git a/rpython/jit/backend/aarch64/codebuilder.py b/rpython/jit/backend/aarch64/codebuilder.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/aarch64/codebuilder.py @@ -0,0 +1,61 @@ + +from rpython.jit.backend.llsupport.asmmemmgr import BlockBuilderMixin +from rpython.jit.backend.aarch64.locations import RegisterLocation + +class AbstractAarch64Builder(object): + def write32(self, word): + self.writechar(chr(word & 0xFF)) + self.writechar(chr((word >> 8) & 0xFF)) + self.writechar(chr((word >> 16) & 0xFF)) + self.writechar(chr((word >> 24) & 0xFF)) + + def RET_r(self, arg): + self.write32((0b1101011001011111 << 16) | (arg << 5)) + + def STP_rr_preindex(self, reg1, reg2, rn, offset): + base = 0b1010100110 + assert -512 <= offset < 512 + assert offset & 0x7 == 0 + self.write32((base << 22) | ((0x7F & (offset >> 3)) << 15) | + (reg2 << 10) | (rn << 5) | reg1) + +class InstrBuilder(BlockBuilderMixin, AbstractAarch64Builder): + + def __init__(self, arch_version=7): + AbstractAarch64Builder.__init__(self) + self.init_block_builder() + # + # ResOperation --> offset in the assembly. + # ops_offset[None] represents the beginning of the code after the last op + # (i.e., the tail of the loop) + self.ops_offset = {} + + def mark_op(self, op): + pos = self.get_relative_pos() + self.ops_offset[op] = pos + + def _dump_trace(self, addr, name, formatter=-1): + if not we_are_translated(): + if formatter != -1: + name = name % formatter + dir = udir.ensure('asm', dir=True) + f = dir.join(name).open('wb') + data = rffi.cast(rffi.CCHARP, addr) + for i in range(self.currpos()): + f.write(data[i]) + f.close() + + def clear_cache(self, addr): + if we_are_translated(): + startaddr = rffi.cast(llmemory.Address, addr) + endaddr = rffi.cast(llmemory.Address, + addr + self.get_relative_pos()) + clear_cache(startaddr, endaddr) + + def copy_to_raw_memory(self, addr): + self._copy_to_raw_memory(addr) + self.clear_cache(addr) + self._dump(addr, "jit-backend-dump", 'arm') + + def currpos(self): + return self.get_relative_pos() diff --git a/rpython/jit/backend/aarch64/locations.py b/rpython/jit/backend/aarch64/locations.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/aarch64/locations.py @@ -0,0 +1,116 @@ + +from rpython.jit.backend.aarch64.arch import WORD, JITFRAME_FIXED_SIZE +from rpython.jit.metainterp.history import INT, FLOAT + +class AssemblerLocation(object): + _immutable_ = True + type = INT + + def is_imm(self): + return False + + def is_stack(self): + return False + + def is_raw_sp(self): + return False + + def is_core_reg(self): + return False + + def is_vfp_reg(self): + return False + + def is_imm_float(self): + return False + + def is_float(self): + return False + + def as_key(self): + raise NotImplementedError + + def get_position(self): + raise NotImplementedError # only for stack + +class RegisterLocation(AssemblerLocation): + _immutable_ = True + + def __init__(self, value): + self.value = value + + def __repr__(self): + return 'x%d' % self.value + + def is_core_reg(self): + return True + + def as_key(self): # 0 <= as_key <= 30, 31 being zero register + xxx + return self.value + +class VFPRegisterLocation(RegisterLocation): + _immutable_ = True + type = FLOAT + + def __repr__(self): + return 'vfp(d%d)' % self.value + + def is_core_reg(self): + return False + + def is_vfp_reg(self): + return True + + def as_key(self): # 40 <= as_key <= 71 + xxx + return self.value + 40 + + def is_float(self): + return True + +class StackLocation(AssemblerLocation): + _immutable_ = True + + def __init__(self, position, fp_offset, type=INT): + self.position = position + self.value = fp_offset + self.type = type + + def __repr__(self): + return 'FP(%s)+%d' % (self.type, self.position,) + + def location_code(self): + return 'b' + + def get_position(self): + return self.position + + def assembler(self): + return repr(self) + + def is_stack(self): + return True + + def as_key(self): # an aligned word + 10000 + XXX + return self.position + 10000 + + def is_float(self): + return self.type == FLOAT + + +class ZeroRegister(AssemblerLocation): + _immutable_ = True + + def __init__(self): + self.value = 31 + + def __repr__(self): + return "xzr" + + def as_key(self): + return 31 + +def get_fp_offset(base_ofs, position): + return base_ofs + WORD * (position + JITFRAME_FIXED_SIZE) diff --git a/rpython/jit/backend/aarch64/opassembler.py b/rpython/jit/backend/aarch64/opassembler.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/aarch64/opassembler.py @@ -0,0 +1,5 @@ + +from rpython.jit.backend.llsupport.assembler import GuardToken, BaseAssembler + +class ResOpAssembler(BaseAssembler): + pass diff --git a/rpython/jit/backend/aarch64/regalloc.py b/rpython/jit/backend/aarch64/regalloc.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/aarch64/regalloc.py @@ -0,0 +1,170 @@ + +from rpython.jit.backend.aarch64 import registers as r +from rpython.jit.backend.aarch64 import locations + +from rpython.jit.metainterp.history import (Const, ConstInt, ConstFloat, + ConstPtr, + INT, REF, FLOAT) +from rpython.jit.metainterp.history import TargetToken +from rpython.jit.backend.llsupport.regalloc import FrameManager, \ + RegisterManager, TempVar, compute_vars_longevity, BaseRegalloc, \ + get_scale + +class ARMFrameManager(FrameManager): + + def __init__(self, base_ofs): + FrameManager.__init__(self) + self.base_ofs = base_ofs + + def frame_pos(self, i, box_type): + return locations.StackLocation(i, locations.get_fp_offset(self.base_ofs, i), box_type) + + @staticmethod + def frame_size(type): + return 1 + + @staticmethod + def get_loc_index(loc): + assert loc.is_stack() + return loc.position + +class ARMRegisterManager(RegisterManager): + def return_constant(self, v, forbidden_vars=[], selected_reg=None): + self._check_type(v) + if isinstance(v, Const): + if isinstance(v, ConstPtr): + tp = REF + elif isinstance(v, ConstFloat): + tp = FLOAT + else: + tp = INT + loc = self.get_scratch_reg(tp, + self.temp_boxes + forbidden_vars, + selected_reg=selected_reg) + immvalue = self.convert_to_imm(v) + self.assembler.load(loc, immvalue) + return loc + else: + return RegisterManager.return_constant(self, v, + forbidden_vars, selected_reg) + + +class VFPRegisterManager(ARMRegisterManager): + all_regs = r.all_vfp_regs + box_types = [FLOAT] + save_around_call_regs = r.all_vfp_regs + + def convert_to_imm(self, c): + adr = self.assembler.datablockwrapper.malloc_aligned(8, 8) + x = c.getfloatstorage() + rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE), adr)[0] = x + return locations.ConstFloatLoc(adr) + + def __init__(self, longevity, frame_manager=None, assembler=None): + RegisterManager.__init__(self, longevity, frame_manager, assembler) + + def after_call(self, v): + """ Adjust registers according to the result of the call, + which is in variable v. + """ + self._check_type(v) + reg = self.force_allocate_reg(v, selected_reg=r.d0) + return reg + + def get_scratch_reg(self, type=FLOAT, forbidden_vars=[], selected_reg=None): + assert type == FLOAT # for now + box = TempFloat() + self.temp_boxes.append(box) + reg = self.force_allocate_reg(box, forbidden_vars=forbidden_vars, + selected_reg=selected_reg) + return reg + + +class CoreRegisterManager(ARMRegisterManager): + all_regs = r.all_regs + box_types = None # or a list of acceptable types + no_lower_byte_regs = all_regs + save_around_call_regs = r.caller_resp + frame_reg = r.fp + + def __init__(self, longevity, frame_manager=None, assembler=None): + RegisterManager.__init__(self, longevity, frame_manager, assembler) + + def call_result_location(self, v): + return r.r0 + + def convert_to_imm(self, c): + if isinstance(c, ConstInt): + val = rffi.cast(rffi.INT, c.value) + return locations.ImmLocation(val) + else: + assert isinstance(c, ConstPtr) + return locations.ImmLocation(rffi.cast(lltype.Signed, c.value)) + assert 0 + + def get_scratch_reg(self, type=INT, forbidden_vars=[], selected_reg=None): + assert type == INT or type == REF + box = None + if type == INT: + box = TempInt() + else: + box = TempPtr() + self.temp_boxes.append(box) + reg = self.force_allocate_reg(box, forbidden_vars=forbidden_vars, + selected_reg=selected_reg) + return reg + + def get_free_reg(self): + free_regs = self.free_regs + for i in range(len(free_regs) - 1, -1, -1): + if free_regs[i] in self.save_around_call_regs: + continue + return free_regs[i] + +class Regalloc(BaseRegalloc): + + def __init__(self, assembler): + self.cpu = assembler.cpu + self.assembler = assembler + self.frame_manager = None + self.jump_target_descr = None + self.final_jump_op = None + + def _prepare(self, inputargs, operations, allgcrefs): + cpu = self.cpu + self.fm = ARMFrameManager(cpu.get_baseofs_of_frame_field()) + self.frame_manager = self.fm + operations = cpu.gc_ll_descr.rewrite_assembler(cpu, operations, + allgcrefs) + # compute longevity of variables + longevity, last_real_usage = compute_vars_longevity(inputargs, operations) + self.longevity = longevity + self.last_real_usage = last_real_usage + fm = self.frame_manager + asm = self.assembler + self.vfprm = VFPRegisterManager(longevity, fm, asm) + self.rm = CoreRegisterManager(longevity, fm, asm) + return operations + + def prepare_loop(self, inputargs, operations, looptoken, allgcrefs): + operations = self._prepare(inputargs, operations, allgcrefs) + self._set_initial_bindings(inputargs, looptoken) + self.possibly_free_vars(list(inputargs)) + return operations + + def possibly_free_var(self, var): + if var.type == FLOAT: + self.vfprm.possibly_free_var(var) + else: + self.rm.possibly_free_var(var) + + def possibly_free_vars_for_op(self, op): + for i in range(op.numargs()): + var = op.getarg(i) + if var is not None: # xxx kludgy + self.possibly_free_var(var) + + def possibly_free_vars(self, vars): + for var in vars: + if var is not None: # xxx kludgy + self.possibly_free_var(var) diff --git a/rpython/jit/backend/aarch64/registers.py b/rpython/jit/backend/aarch64/registers.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/aarch64/registers.py @@ -0,0 +1,25 @@ + +from rpython.jit.backend.aarch64.locations import (RegisterLocation, + ZeroRegister, VFPRegisterLocation) + + +registers = [RegisterLocation(i) for i in range(31)] +sp = wzr = ZeroRegister() +[x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, + x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, + x21, x22, x23, x24, x25, x26, x27, x28, x29, x30] = registers + +vfpregisters = [VFPRegisterLocation(i) for i in range(32)] +all_vfp_regs = vfpregisters[:16] +all_regs = registers[:16] + [x19, x20, x21, x22] + +lr = x30 +fp = x29 +ip1 = x17 +ip0 = x16 + +callee_resp = [x19, x20, x21, x22, fp] + +argument_regs = caller_resp = [x0, x1, x2, x3, x4, x5, x6, x7] + +callee_saved_registers = callee_resp + [lr] diff --git a/rpython/jit/backend/aarch64/runner.py b/rpython/jit/backend/aarch64/runner.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/aarch64/runner.py @@ -0,0 +1,27 @@ + +from rpython.rtyper.lltypesystem import llmemory, lltype +from rpython.jit.backend.aarch64.assembler import AssemblerARM64 +from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU + +class CPU_ARM64(AbstractLLCPU): + """ARM 64""" + backend_name = "aarch64" + + IS_64_BIT = True + + def __init__(self, rtyper, stats, opts=None, translate_support_code=False, + gcdescr=None): + AbstractLLCPU.__init__(self, rtyper, stats, opts, + translate_support_code, gcdescr) + + def setup(self): + self.assembler = AssemblerARM64(self, self.translate_support_code) + + def setup_once(self): + self.assembler.setup_once() + + def cast_ptr_to_int(x): + adr = llmemory.cast_ptr_to_adr(x) + return CPU_ARM64.cast_adr_to_int(adr) + cast_ptr_to_int._annspecialcase_ = 'specialize:arglltype(0)' + cast_ptr_to_int = staticmethod(cast_ptr_to_int) diff --git a/rpython/jit/backend/aarch64/test/__init__.py b/rpython/jit/backend/aarch64/test/__init__.py new file mode 100644 diff --git a/rpython/jit/backend/aarch64/test/gen.py b/rpython/jit/backend/aarch64/test/gen.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/aarch64/test/gen.py @@ -0,0 +1,51 @@ +import os +from rpython.tool.udir import udir +import tempfile + +class ASMInstruction(object): + + asm_opts = '-march=armv8-a' + body = """.section .text +_start: .global _start + .global main + b main +main: + .ascii "START " + %s + .ascii "END " +""" + begin_tag = 'START ' + end_tag = 'END ' + base_name = 'test_%d.asm' + index = 0 + + def __init__(self, instr): + self.instr = instr + self.file = udir.join(self.base_name % self.index) + while self.file.check(): + self.index += 1 + self.file = udir.join(self.base_name % self.index) + + def encode(self): + f = open("%s/a.out" % (udir),'rb') + data = f.read() + f.close() + i = data.find(self.begin_tag) + assert i>=0 + j = data.find(self.end_tag, i) + assert j>=0 + as_code = data[i+len(self.begin_tag):j] + return as_code + + def assemble(self, *args): + res = self.body % (self.instr) + self.file.write(res) + os.system("as --fatal-warnings %s %s -o %s/a.out" % (self.asm_opts, self.file, udir)) + + #def __del__(self): + # self.file.close() + +def assemble(instr): + a = ASMInstruction(instr) + a.assemble(instr) + return a.encode() diff --git a/rpython/jit/backend/aarch64/test/test_instr_builder.py b/rpython/jit/backend/aarch64/test/test_instr_builder.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/aarch64/test/test_instr_builder.py @@ -0,0 +1,34 @@ + +from rpython.jit.backend.aarch64 import registers as r +from rpython.jit.backend.aarch64 import codebuilder +from rpython.jit.backend.aarch64.test.gen import assemble + +class CodeBuilder(codebuilder.InstrBuilder): + def __init__(self, arch_version=7): + self.arch_version = arch_version + self.buffer = [] + + def writechar(self, char): + self.buffer.append(char) + + def hexdump(self): + return ''.join(self.buffer) + +class TestInstrBuilder(object): + def setup_method(self, meth): + self.cb = CodeBuilder() + + def test_ret(self): + self.cb.RET_r(r.x0.value) + res = self.cb.hexdump() + exp = assemble('RET x0') + assert res == exp + self.cb = CodeBuilder() + self.cb.RET_r(r.x0.value) + self.cb.RET_r(r.x5.value) + self.cb.RET_r(r.x3.value) + assert self.cb.hexdump() == assemble('RET x0\nRET x5\n RET x3') + + def test_call_header(self): + self.cb.STP_rr_preindex(r.x29.value, r.x30.value, r.sp.value, -32) + assert self.cb.hexdump() == assemble("STP x29, x30, [sp, -32]!") diff --git a/rpython/jit/backend/aarch64/test/test_runner.py b/rpython/jit/backend/aarch64/test/test_runner.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/aarch64/test/test_runner.py @@ -0,0 +1,46 @@ +import py +from rpython.jit.backend.detect_cpu import getcpuclass +from rpython.jit.backend.test.runner_test import LLtypeBackendTest,\ + boxfloat, constfloat +from rpython.jit.metainterp.history import BasicFailDescr, BasicFinalDescr +from rpython.jit.metainterp.resoperation import (ResOperation, rop, + InputArgInt) +from rpython.jit.tool.oparser import parse +from rpython.rtyper.lltypesystem import lltype, llmemory +from rpython.rtyper import rclass +from rpython.rtyper.annlowlevel import llhelper +from rpython.jit.codewriter.effectinfo import EffectInfo +from rpython.jit.metainterp.history import JitCellToken, TargetToken +from rpython.jit.codewriter import longlong + + +CPU = getcpuclass() + +class FakeStats(object): + pass + + +class TestARM64(LLtypeBackendTest): + + # for the individual tests see + # ====> ../../test/runner_test.py + + #add_loop_instructions = 'ldr; adds; cmp; beq; b;' + #if arch_version == 7: + # bridge_loop_instructions = ('ldr; movw; nop; cmp; bge; ' + # 'push; movw; movt; push; movw; movt; ' + # 'blx; movw; movt; bx;') + #else: + # bridge_loop_instructions = ('ldr; mov; nop; nop; nop; cmp; bge; ' + # 'push; ldr; mov; ' + # '[^;]+; ' # inline constant + # 'push; ldr; mov; ' + # '[^;]+; ' # inline constant + # 'blx; ldr; mov; ' + # '[^;]+; ' # inline constant + # 'bx;') + + def get_cpu(self): + cpu = CPU(rtyper=None, stats=FakeStats()) + cpu.setup_once() + return cpu diff --git a/rpython/jit/backend/arm/test/gen.py b/rpython/jit/backend/arm/test/gen.py --- a/rpython/jit/backend/arm/test/gen.py +++ b/rpython/jit/backend/arm/test/gen.py @@ -2,6 +2,7 @@ from rpython.tool.udir import udir import tempfile from rpython.jit.backend.arm.test.support import AS + class ASMInstruction(object): asm_opts = '-mfpu=neon -mcpu=cortex-a8 -march=armv7-a' diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -14,6 +14,7 @@ MODEL_X86_NO_SSE2 = 'x86-without-sse2' MODEL_X86_64 = 'x86-64' MODEL_ARM = 'arm' +MODEL_ARM64 = 'aarch64' MODEL_PPC_64 = 'ppc-64' MODEL_S390_64 = 's390x' # don't use '_' in the model strings; they are replaced by '-' @@ -25,6 +26,7 @@ mapping = { MODEL_X86_64: ['__amd64__', '__amd64', '__x86_64__', '__x86_64', '_M_X64', '_M_AMD64'], MODEL_ARM: ['__arm__', '__thumb__','_M_ARM_EP'], + MODEL_ARM64: ['__aarch64__'], MODEL_X86: ['i386', '__i386', '__i386__', '__i686__','_M_IX86'], MODEL_PPC_64: ['__powerpc64__'], MODEL_S390_64:['__s390x__'], @@ -68,6 +70,7 @@ 'amd64': MODEL_X86, # freebsd 'AMD64': MODEL_X86, # win64 'armv8l': MODEL_ARM, # 32-bit ARMv8 + 'aarch64': MODEL_ARM64, 'armv7l': MODEL_ARM, 'armv6l': MODEL_ARM, 'arm': MODEL_ARM, # freebsd @@ -119,6 +122,8 @@ return "rpython.jit.backend.x86.runner", "CPU_X86_64" elif backend_name == MODEL_ARM: return "rpython.jit.backend.arm.runner", "CPU_ARM" + elif backend_name == MODEL_ARM64: + return "rpython.jit.backend.aarch64.runner", "CPU_ARM64" elif backend_name == MODEL_PPC_64: return "rpython.jit.backend.ppc.runner", "PPC_CPU" elif backend_name == MODEL_S390_64: _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit