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

Reply via email to