PageRenderTime 47ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/rpython/jit/backend/zarch/codebuilder.py

https://bitbucket.org/pypy/pypy/
Python | 264 lines | 216 code | 32 blank | 16 comment | 24 complexity | d552254d2f3931be1504af1115be40ab MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from rpython.jit.backend.zarch import conditions as c
  2. from rpython.jit.backend.zarch import registers as r
  3. from rpython.jit.backend.zarch import locations as l
  4. from rpython.jit.backend.zarch.arch import STD_FRAME_SIZE_IN_BYTES
  5. from rpython.jit.backend.zarch.instruction_builder import build_instr_codes
  6. from rpython.jit.backend.llsupport.asmmemmgr import BlockBuilderMixin
  7. from rpython.jit.backend.llsupport.assembler import GuardToken
  8. from rpython.rlib.objectmodel import we_are_translated
  9. from rpython.rlib.unroll import unrolling_iterable
  10. from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
  11. from rpython.tool.udir import udir
  12. from rpython.jit.backend.detect_cpu import autodetect
  13. from rpython.jit.backend.zarch.arch import WORD
  14. clear_cache = rffi.llexternal(
  15. "__clear_cache",
  16. [llmemory.Address, llmemory.Address],
  17. lltype.Void,
  18. _nowrapper=True,
  19. sandboxsafe=True)
  20. def binary_helper_call(name):
  21. function = getattr(support, 'arm_%s' % name)
  22. def f(self, c=c.AL):
  23. """Generates a call to a helper function, takes its
  24. arguments in r0 and r1, result is placed in r0"""
  25. addr = rffi.cast(lltype.Signed, function)
  26. self.BL(addr, c)
  27. return f
  28. class ZARCHGuardToken(GuardToken):
  29. def __init__(self, cpu, gcmap, descr, failargs, faillocs,
  30. guard_opnum, frame_depth, faildescrindex, fcond=c.cond_none):
  31. GuardToken.__init__(self, cpu, gcmap, descr, failargs, faillocs,
  32. guard_opnum, frame_depth, faildescrindex)
  33. self.fcond = fcond
  34. class AbstractZARCHBuilder(object):
  35. def write_i64(self, word):
  36. self.writechar(chr((word >> 56) & 0xFF))
  37. self.writechar(chr((word >> 48) & 0xFF))
  38. self.writechar(chr((word >> 40) & 0xFF))
  39. self.writechar(chr((word >> 32) & 0xFF))
  40. self.writechar(chr((word >> 24) & 0xFF))
  41. self.writechar(chr((word >> 16) & 0xFF))
  42. self.writechar(chr((word >> 8) & 0xFF))
  43. self.writechar(chr(word & 0xFF))
  44. def write_i32(self, word):
  45. self.writechar(chr((word >> 24) & 0xFF))
  46. self.writechar(chr((word >> 16) & 0xFF))
  47. self.writechar(chr((word >> 8) & 0xFF))
  48. self.writechar(chr(word & 0xFF))
  49. def write_i16(self, word):
  50. self.writechar(chr((word >> 8) & 0xFF))
  51. self.writechar(chr(word & 0xFF))
  52. def write(self, bytestr):
  53. for char in bytestr:
  54. self.writechar(char)
  55. build_instr_codes(AbstractZARCHBuilder)
  56. class InstrBuilder(BlockBuilderMixin, AbstractZARCHBuilder):
  57. RAW_CALL_REG = r.r14
  58. def __init__(self, pool=None):
  59. AbstractZARCHBuilder.__init__(self)
  60. self.init_block_builder()
  61. self.pool = pool
  62. #
  63. # ResOperation --> offset in the assembly.
  64. # ops_offset[None] represents the beginning of the code after the last op
  65. # (i.e., the tail of the loop)
  66. self.ops_offset = {}
  67. def mark_op(self, op):
  68. pos = self.get_relative_pos()
  69. self.ops_offset[op] = pos
  70. def _dump_trace(self, addr, name, formatter=-1):
  71. if not we_are_translated():
  72. if formatter != -1:
  73. name = name % formatter
  74. dir = udir.ensure('asm', dir=True)
  75. f = dir.join(name).open('wb')
  76. data = rffi.cast(rffi.CCHARP, addr)
  77. for i in range(self.currpos()):
  78. f.write(data[i])
  79. f.close()
  80. def clear_cache(self, addr):
  81. if we_are_translated():
  82. startaddr = rffi.cast(llmemory.Address, addr)
  83. endaddr = rffi.cast(llmemory.Address,
  84. addr + self.get_relative_pos())
  85. clear_cache(startaddr, endaddr)
  86. def copy_to_raw_memory(self, addr):
  87. self._copy_to_raw_memory(addr)
  88. self.clear_cache(addr)
  89. self._dump(addr, "jit-backend-dump", "s390x")
  90. def load(self, treg, sreg, offset):
  91. self.LG(treg, l.addr(offset, sreg))
  92. def store(self, val, dst, off):
  93. self.STG(val, l.addr(off, dst))
  94. def store_update(self, valreg, treg, offset):
  95. self.STG(valreg, l.addr(offset, treg))
  96. def nop(self):
  97. # if the mask is zero it act as a NOP
  98. # there is no special 'no operation' instruction
  99. self.BCR_rr(0x0, 0x0)
  100. def currpos(self):
  101. return self.get_relative_pos()
  102. def b_abs(self, addr):
  103. self.load_imm(r.r14, addr)
  104. self.BCR(c.ANY, r.r14)
  105. def b_cond_offset(self, offset, condition):
  106. assert condition != c.cond_none
  107. self.BRCL(condition, l.imm(offset))
  108. def b_offset(self, reladdr):
  109. offset = reladdr - self.get_relative_pos()
  110. if -2**15 <= offset <= 2**15-1:
  111. self.BRC(c.ANY, l.imm(offset))
  112. else:
  113. # we have big loops!
  114. self.BRCL(c.ANY, l.imm(offset))
  115. def reserve_guard_branch(self):
  116. self.BRCL(l.imm(0x0), l.imm(0))
  117. def trap(self):
  118. self.TRAP2()
  119. def trace(self):
  120. self.LGHI(r.r2, l.imm(17))
  121. self.XGR(r.r3, r.r3)
  122. self.SVC(l.imm(17))
  123. def cmp_op(self, a, b, pool=False, imm=False, signed=True, fp=False):
  124. if fp == True:
  125. if pool:
  126. self.CDB(a, b)
  127. else:
  128. self.CDBR(a, b)
  129. else:
  130. if signed:
  131. if pool:
  132. # 64 bit immediate signed
  133. self.CG(a, b)
  134. elif imm:
  135. self.CGFI(a, b)
  136. else:
  137. # 64 bit signed
  138. self.CGR(a, b)
  139. else:
  140. if pool:
  141. # 64 bit immediate unsigned
  142. self.CLG(a, b)
  143. elif imm:
  144. self.CLGFI(a, b)
  145. else:
  146. # 64 bit unsigned
  147. self.CLGR(a, b)
  148. def load_imm(self, dest_reg, word):
  149. if -2**15 <= word <= 2**15-1:
  150. self.LGHI(dest_reg, l.imm(word))
  151. elif -2**31 <= word <= 2**31-1:
  152. self.LGFI(dest_reg, l.imm(word))
  153. else:
  154. if self.pool and self.pool.contains_constant(word):
  155. self.LG(dest_reg, l.pool(self.pool.get_direct_offset(word)))
  156. return
  157. self.IILF(dest_reg, l.imm(word & 0xFFFFffff))
  158. self.IIHF(dest_reg, l.imm((word >> 32) & 0xFFFFffff))
  159. def load_imm_plus(self, dest_reg, word):
  160. """Like load_imm(), but with one instruction less, and
  161. leaves the loaded value off by some signed 16-bit difference.
  162. Returns that difference."""
  163. diff = rffi.cast(lltype.Signed, rffi.cast(rffi.SHORT, word))
  164. word -= diff
  165. assert word & 0xFFFF == 0
  166. self.load_imm(dest_reg, word)
  167. return diff
  168. def sync(self):
  169. self.BCR_rr(0xf,0)
  170. def raw_call(self, call_reg=r.r14):
  171. """Emit a call to the address stored in the register 'call_reg',
  172. which must be either RAW_CALL_REG or r11. This is a regular C
  173. function pointer, which means on big-endian that it is actually
  174. the address of a three-words descriptor.
  175. """
  176. self.BASR(r.r14, call_reg)
  177. def reserve_cond_jump(self, short=False):
  178. self.trap() # conditional jump, patched later
  179. self.trap()
  180. if not short:
  181. # 6 bytes instead of 2
  182. self.trap()
  183. def branch_absolute(self, addr):
  184. self.load_imm(r.r14, addr)
  185. self.BASR(r.r14, r.r14)
  186. def store_link(self):
  187. self.STMG(r.r14, r.r15, l.addr(14*WORD, r.SP))
  188. def restore_link(self):
  189. off = STD_FRAME_SIZE_IN_BYTES
  190. self.LMG(r.r14, r.r15, l.addr(off+14*WORD, r.SP))
  191. def push_std_frame(self, additional_bytes=0):
  192. off = (STD_FRAME_SIZE_IN_BYTES + additional_bytes)
  193. self.STG(r.SP, l.addr(-off, r.SP))
  194. self.LAY(r.SP, l.addr(-off, r.SP))
  195. def pop_std_frame(self, additional_bytes=0):
  196. self.LAY(r.SP, l.addr(STD_FRAME_SIZE_IN_BYTES + additional_bytes, r.SP))
  197. def get_assembler_function(self):
  198. "NOT_RPYTHON: tests only"
  199. from rpython.jit.backend.llsupport.asmmemmgr import AsmMemoryManager
  200. class FakeCPU:
  201. HAS_CODEMAP = False
  202. asmmemmgr = AsmMemoryManager()
  203. addr = self.materialize(FakeCPU(), [])
  204. return rffi.cast(lltype.Ptr(lltype.FuncType([], lltype.Signed)), addr)
  205. class OverwritingBuilder(BlockBuilderMixin, AbstractZARCHBuilder):
  206. def __init__(self, mc, start, num_insts=0):
  207. AbstractZARCHBuilder.__init__(self)
  208. self.init_block_builder()
  209. self.mc = mc
  210. self.index = start
  211. def writechar(self, c):
  212. self.mc.overwrite(self.index, c)
  213. self.index += 1
  214. def overwrite(self):
  215. pass
  216. _classes = (AbstractZARCHBuilder,)
  217. # Used to build the MachineCodeBlockWrapper
  218. all_instructions = sorted([name for cls in _classes for name in cls.__dict__ \
  219. if name.split('_')[0].isupper() and '_' in name and \
  220. not name.endswith('_byte_count')])