Author: Maciej Fijalkowski <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit