PageRenderTime 58ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/rpython/jit/backend/arm/opassembler.py

https://bitbucket.org/pypy/pypy/
Python | 1264 lines | 1005 code | 126 blank | 133 comment | 141 complexity | 9cc5d526a4d64b1029651e77a2346b9b MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. from __future__ import with_statement
  2. from rpython.jit.backend.arm import conditions as c
  3. from rpython.jit.backend.arm import registers as r
  4. from rpython.jit.backend.arm import shift
  5. from rpython.jit.backend.arm.arch import WORD, DOUBLE_WORD, JITFRAME_FIXED_SIZE
  6. from rpython.jit.backend.arm.helper.assembler import (
  7. gen_emit_op_unary_cmp,
  8. gen_emit_op_ri,
  9. gen_emit_cmp_op,
  10. gen_emit_float_op,
  11. gen_emit_float_cmp_op,
  12. gen_emit_unary_float_op,
  13. saved_registers)
  14. from rpython.jit.backend.arm.helper.regalloc import check_imm_arg
  15. from rpython.jit.backend.arm.helper.regalloc import VMEM_imm_size
  16. from rpython.jit.backend.arm.codebuilder import InstrBuilder, OverwritingBuilder
  17. from rpython.jit.backend.arm.jump import remap_frame_layout
  18. from rpython.jit.backend.arm.regalloc import TempVar
  19. from rpython.jit.backend.arm.locations import imm, RawSPStackLocation
  20. from rpython.jit.backend.llsupport import symbolic
  21. from rpython.jit.backend.llsupport.gcmap import allocate_gcmap
  22. from rpython.jit.backend.llsupport.assembler import GuardToken, BaseAssembler
  23. from rpython.jit.backend.llsupport.regalloc import get_scale
  24. from rpython.jit.metainterp.history import (AbstractFailDescr, ConstInt,
  25. INT, FLOAT, REF)
  26. from rpython.jit.metainterp.history import TargetToken
  27. from rpython.jit.metainterp.resoperation import rop
  28. from rpython.rlib.objectmodel import we_are_translated
  29. from rpython.rtyper.lltypesystem import rstr, rffi, lltype
  30. from rpython.rtyper.annlowlevel import cast_instance_to_gcref
  31. from rpython.rtyper import rclass
  32. from rpython.jit.backend.arm import callbuilder
  33. from rpython.rlib.rarithmetic import r_uint
  34. class ArmGuardToken(GuardToken):
  35. def __init__(self, cpu, gcmap, faildescr, failargs, fail_locs,
  36. offset, guard_opnum, frame_depth, faildescrindex, fcond=c.AL):
  37. GuardToken.__init__(self, cpu, gcmap, faildescr, failargs, fail_locs,
  38. guard_opnum, frame_depth, faildescrindex)
  39. self.fcond = fcond
  40. self.offset = offset
  41. class ResOpAssembler(BaseAssembler):
  42. def emit_op_int_add(self, op, arglocs, regalloc, fcond):
  43. return self.int_add_impl(op, arglocs, regalloc, fcond)
  44. emit_op_nursery_ptr_increment = emit_op_int_add
  45. def int_add_impl(self, op, arglocs, regalloc, fcond, flags=False):
  46. l0, l1, res = arglocs
  47. if flags:
  48. s = 1
  49. else:
  50. s = 0
  51. if l0.is_imm():
  52. self.mc.ADD_ri(res.value, l1.value, imm=l0.value, s=s)
  53. elif l1.is_imm():
  54. self.mc.ADD_ri(res.value, l0.value, imm=l1.value, s=s)
  55. else:
  56. self.mc.ADD_rr(res.value, l0.value, l1.value, s=1)
  57. return fcond
  58. def emit_op_int_sub(self, op, arglocs, regalloc, fcond, flags=False):
  59. return self.int_sub_impl(op, arglocs, regalloc, fcond)
  60. def int_sub_impl(self, op, arglocs, regalloc, fcond, flags=False):
  61. l0, l1, res = arglocs
  62. if flags:
  63. s = 1
  64. else:
  65. s = 0
  66. if l0.is_imm():
  67. value = l0.getint()
  68. assert value >= 0
  69. # reverse substract ftw
  70. self.mc.RSB_ri(res.value, l1.value, value, s=s)
  71. elif l1.is_imm():
  72. value = l1.getint()
  73. assert value >= 0
  74. self.mc.SUB_ri(res.value, l0.value, value, s=s)
  75. else:
  76. self.mc.SUB_rr(res.value, l0.value, l1.value, s=s)
  77. return fcond
  78. def emit_op_int_mul(self, op, arglocs, regalloc, fcond):
  79. reg1, reg2, res = arglocs
  80. self.mc.MUL(res.value, reg1.value, reg2.value)
  81. return fcond
  82. def emit_op_uint_mul_high(self, op, arglocs, regalloc, fcond):
  83. reg1, reg2, res = arglocs
  84. self.mc.UMULL(r.ip.value, res.value, reg1.value, reg2.value)
  85. return fcond
  86. def emit_op_int_force_ge_zero(self, op, arglocs, regalloc, fcond):
  87. arg, res = arglocs
  88. self.mc.CMP_ri(arg.value, 0)
  89. self.mc.MOV_ri(res.value, 0, cond=c.LT)
  90. self.mc.MOV_rr(res.value, arg.value, cond=c.GE)
  91. return fcond
  92. def emit_op_int_signext(self, op, arglocs, regalloc, fcond):
  93. arg, numbytes, res = arglocs
  94. assert numbytes.is_imm()
  95. if numbytes.value == 1:
  96. self.mc.SXTB_rr(res.value, arg.value)
  97. elif numbytes.value == 2:
  98. self.mc.SXTH_rr(res.value, arg.value)
  99. else:
  100. raise AssertionError("bad number of bytes")
  101. return fcond
  102. #ref: http://blogs.arm.com/software-enablement/detecting-overflow-from-mul/
  103. def emit_op_int_mul_ovf(self, op, arglocs, regalloc, fcond):
  104. reg1 = arglocs[0]
  105. reg2 = arglocs[1]
  106. res = arglocs[2]
  107. self.mc.SMULL(res.value, r.ip.value, reg1.value, reg2.value,
  108. cond=fcond)
  109. self.mc.CMP_rr(r.ip.value, res.value, shifttype=shift.ASR,
  110. imm=31, cond=fcond)
  111. self.guard_success_cc = c.EQ
  112. return fcond
  113. def emit_op_int_add_ovf(self, op, arglocs, regalloc, fcond):
  114. fcond = self.int_add_impl(op, arglocs, regalloc, fcond, flags=True)
  115. self.guard_success_cc = c.VC
  116. return fcond
  117. def emit_op_int_sub_ovf(self, op, arglocs, regalloc, fcond):
  118. fcond = self.int_sub_impl(op, arglocs, regalloc, fcond, flags=True)
  119. self.guard_success_cc = c.VC
  120. return fcond
  121. emit_op_int_and = gen_emit_op_ri('int_and', 'AND')
  122. emit_op_int_or = gen_emit_op_ri('int_or', 'ORR')
  123. emit_op_int_xor = gen_emit_op_ri('int_xor', 'EOR')
  124. emit_op_int_lshift = gen_emit_op_ri('int_lshift', 'LSL')
  125. emit_op_int_rshift = gen_emit_op_ri('int_rshift', 'ASR')
  126. emit_op_uint_rshift = gen_emit_op_ri('uint_rshift', 'LSR')
  127. emit_op_int_lt = gen_emit_cmp_op('int_lt', c.LT)
  128. emit_op_int_le = gen_emit_cmp_op('int_le', c.LE)
  129. emit_op_int_eq = gen_emit_cmp_op('int_eq', c.EQ)
  130. emit_op_int_ne = gen_emit_cmp_op('int_ne', c.NE)
  131. emit_op_int_gt = gen_emit_cmp_op('int_gt', c.GT)
  132. emit_op_int_ge = gen_emit_cmp_op('int_ge', c.GE)
  133. emit_op_uint_le = gen_emit_cmp_op('uint_le', c.LS)
  134. emit_op_uint_gt = gen_emit_cmp_op('uint_gt', c.HI)
  135. emit_op_uint_lt = gen_emit_cmp_op('uint_lt', c.LO)
  136. emit_op_uint_ge = gen_emit_cmp_op('uint_ge', c.HS)
  137. emit_op_ptr_eq = emit_op_instance_ptr_eq = emit_op_int_eq
  138. emit_op_ptr_ne = emit_op_instance_ptr_ne = emit_op_int_ne
  139. emit_op_int_is_true = gen_emit_op_unary_cmp('int_is_true', c.NE)
  140. emit_op_int_is_zero = gen_emit_op_unary_cmp('int_is_zero', c.EQ)
  141. def emit_op_int_invert(self, op, arglocs, regalloc, fcond):
  142. reg, res = arglocs
  143. self.mc.MVN_rr(res.value, reg.value)
  144. return fcond
  145. def emit_op_int_neg(self, op, arglocs, regalloc, fcond):
  146. l0, resloc = arglocs
  147. self.mc.RSB_ri(resloc.value, l0.value, imm=0)
  148. return fcond
  149. def build_guard_token(self, op, frame_depth, arglocs, offset, fcond):
  150. assert isinstance(fcond, int)
  151. descr = op.getdescr()
  152. assert isinstance(descr, AbstractFailDescr)
  153. gcmap = allocate_gcmap(self, frame_depth, JITFRAME_FIXED_SIZE)
  154. faildescrindex = self.get_gcref_from_faildescr(descr)
  155. token = ArmGuardToken(self.cpu, gcmap,
  156. descr,
  157. failargs=op.getfailargs(),
  158. fail_locs=arglocs,
  159. offset=offset,
  160. guard_opnum=op.getopnum(),
  161. frame_depth=frame_depth,
  162. faildescrindex=faildescrindex,
  163. fcond=fcond)
  164. return token
  165. def _emit_guard(self, op, arglocs, is_guard_not_invalidated=False):
  166. if is_guard_not_invalidated:
  167. fcond = c.cond_none
  168. else:
  169. fcond = self.guard_success_cc
  170. self.guard_success_cc = c.cond_none
  171. assert fcond != c.cond_none
  172. pos = self.mc.currpos()
  173. token = self.build_guard_token(op, arglocs[0].value, arglocs[1:], pos, fcond)
  174. self.pending_guards.append(token)
  175. assert token.guard_not_invalidated() == is_guard_not_invalidated
  176. # For all guards that are not GUARD_NOT_INVALIDATED we emit a
  177. # breakpoint to ensure the location is patched correctly. In the case
  178. # of GUARD_NOT_INVALIDATED we use just a NOP, because it is only
  179. # eventually patched at a later point.
  180. if is_guard_not_invalidated:
  181. self.mc.NOP()
  182. else:
  183. self.mc.BKPT()
  184. return c.AL
  185. def emit_op_guard_true(self, op, arglocs, regalloc, fcond):
  186. fcond = self._emit_guard(op, arglocs)
  187. return fcond
  188. def emit_op_guard_false(self, op, arglocs, regalloc, fcond):
  189. self.guard_success_cc = c.get_opposite_of(self.guard_success_cc)
  190. fcond = self._emit_guard(op, arglocs)
  191. return fcond
  192. def emit_op_guard_value(self, op, arglocs, regalloc, fcond):
  193. l0 = arglocs[0]
  194. l1 = arglocs[1]
  195. failargs = arglocs[2:]
  196. if l0.is_core_reg():
  197. if l1.is_imm():
  198. self.mc.CMP_ri(l0.value, l1.getint())
  199. else:
  200. self.mc.CMP_rr(l0.value, l1.value)
  201. elif l0.is_vfp_reg():
  202. assert l1.is_vfp_reg()
  203. self.mc.VCMP(l0.value, l1.value)
  204. self.mc.VMRS(cond=fcond)
  205. self.guard_success_cc = c.EQ
  206. fcond = self._emit_guard(op, failargs)
  207. return fcond
  208. emit_op_guard_nonnull = emit_op_guard_true
  209. emit_op_guard_isnull = emit_op_guard_false
  210. emit_op_guard_no_overflow = emit_op_guard_true
  211. emit_op_guard_overflow = emit_op_guard_false
  212. def emit_op_guard_class(self, op, arglocs, regalloc, fcond):
  213. self._cmp_guard_class(op, arglocs, regalloc, fcond)
  214. self.guard_success_cc = c.EQ
  215. self._emit_guard(op, arglocs[2:])
  216. return fcond
  217. def emit_op_guard_nonnull_class(self, op, arglocs, regalloc, fcond):
  218. self.mc.CMP_ri(arglocs[0].value, 1)
  219. self._cmp_guard_class(op, arglocs, regalloc, c.HS)
  220. self.guard_success_cc = c.EQ
  221. self._emit_guard(op, arglocs[2:])
  222. return fcond
  223. def _cmp_guard_class(self, op, locs, regalloc, fcond):
  224. offset = self.cpu.vtable_offset
  225. if offset is not None:
  226. self.mc.LDR_ri(r.ip.value, locs[0].value, offset, cond=fcond)
  227. self.mc.gen_load_int(r.lr.value, locs[1].value, cond=fcond)
  228. self.mc.CMP_rr(r.ip.value, r.lr.value, cond=fcond)
  229. else:
  230. expected_typeid = (self.cpu.gc_ll_descr
  231. .get_typeid_from_classptr_if_gcremovetypeptr(locs[1].value))
  232. self._cmp_guard_gc_type(locs[0], expected_typeid, fcond)
  233. def _cmp_guard_gc_type(self, loc_ptr, expected_typeid, fcond=c.AL):
  234. # Note that the typeid half-word is at offset 0 on a little-endian
  235. # machine; it would be at offset 2 or 4 on a big-endian machine.
  236. assert self.cpu.supports_guard_gc_type
  237. self.mc.LDRH_ri(r.ip.value, loc_ptr.value, cond=fcond)
  238. self.mc.gen_load_int(r.lr.value, expected_typeid, cond=fcond)
  239. self.mc.CMP_rr(r.ip.value, r.lr.value, cond=fcond)
  240. def emit_op_guard_gc_type(self, op, arglocs, regalloc, fcond):
  241. self._cmp_guard_gc_type(arglocs[0], arglocs[1].value, fcond)
  242. self.guard_success_cc = c.EQ
  243. self._emit_guard(op, arglocs[2:])
  244. return fcond
  245. def emit_op_guard_is_object(self, op, arglocs, regalloc, fcond):
  246. assert self.cpu.supports_guard_gc_type
  247. loc_object = arglocs[0]
  248. # idea: read the typeid, fetch one byte of the field 'infobits' from
  249. # the big typeinfo table, and check the flag 'T_IS_RPYTHON_INSTANCE'.
  250. self.mc.LDRH_ri(r.ip.value, loc_object.value)
  251. #
  252. base_type_info, shift_by, sizeof_ti = (
  253. self.cpu.gc_ll_descr.get_translated_info_for_typeinfo())
  254. infobits_offset, IS_OBJECT_FLAG = (
  255. self.cpu.gc_ll_descr.get_translated_info_for_guard_is_object())
  256. self.mc.gen_load_int(r.lr.value, base_type_info + infobits_offset)
  257. if shift_by > 0:
  258. self.mc.LSL_ri(r.ip.value, r.ip.value, shift_by)
  259. self.mc.LDRB_rr(r.ip.value, r.ip.value, r.lr.value)
  260. self.mc.TST_ri(r.ip.value, imm=(IS_OBJECT_FLAG & 0xff))
  261. self.guard_success_cc = c.NE
  262. self._emit_guard(op, arglocs[1:])
  263. return fcond
  264. def emit_op_guard_subclass(self, op, arglocs, regalloc, fcond):
  265. assert self.cpu.supports_guard_gc_type
  266. loc_object = arglocs[0]
  267. loc_check_against_class = arglocs[1]
  268. offset = self.cpu.vtable_offset
  269. offset2 = self.cpu.subclassrange_min_offset
  270. if offset is not None:
  271. # read this field to get the vtable pointer
  272. self.mc.LDR_ri(r.ip.value, loc_object.value, offset)
  273. # read the vtable's subclassrange_min field
  274. self.mc.LDR_ri(r.ip.value, r.ip.value, offset2)
  275. else:
  276. # read the typeid
  277. self.mc.LDRH_ri(r.ip.value, loc_object.value)
  278. # read the vtable's subclassrange_min field, as a single
  279. # step with the correct offset
  280. base_type_info, shift_by, sizeof_ti = (
  281. self.cpu.gc_ll_descr.get_translated_info_for_typeinfo())
  282. self.mc.gen_load_int(r.lr.value,
  283. base_type_info + sizeof_ti + offset2)
  284. if shift_by > 0:
  285. self.mc.LSL_ri(r.ip.value, r.ip.value, shift_by)
  286. self.mc.LDR_rr(r.ip.value, r.ip.value, r.lr.value)
  287. # get the two bounds to check against
  288. vtable_ptr = loc_check_against_class.getint()
  289. vtable_ptr = rffi.cast(rclass.CLASSTYPE, vtable_ptr)
  290. check_min = vtable_ptr.subclassrange_min
  291. check_max = vtable_ptr.subclassrange_max
  292. assert check_max > check_min
  293. check_diff = check_max - check_min - 1
  294. # check by doing the unsigned comparison (tmp - min) < (max - min)
  295. self.mc.gen_load_int(r.lr.value, check_min)
  296. self.mc.SUB_rr(r.ip.value, r.ip.value, r.lr.value)
  297. if check_diff <= 0xff:
  298. self.mc.CMP_ri(r.ip.value, check_diff)
  299. else:
  300. self.mc.gen_load_int(r.lr.value, check_diff)
  301. self.mc.CMP_rr(r.ip.value, r.lr.value)
  302. # the guard passes if we get a result of "below or equal"
  303. self.guard_success_cc = c.LS
  304. self._emit_guard(op, arglocs[2:])
  305. return fcond
  306. def emit_op_guard_not_invalidated(self, op, locs, regalloc, fcond):
  307. return self._emit_guard(op, locs, is_guard_not_invalidated=True)
  308. def emit_op_label(self, op, arglocs, regalloc, fcond):
  309. self._check_frame_depth_debug(self.mc)
  310. return fcond
  311. def emit_op_cond_call(self, op, arglocs, regalloc, fcond):
  312. [call_loc] = arglocs
  313. gcmap = regalloc.get_gcmap([call_loc])
  314. assert call_loc is r.r4
  315. jmp_adr = self.mc.currpos()
  316. self.mc.BKPT() # patched later: the conditional jump
  317. #
  318. self.push_gcmap(self.mc, gcmap, store=True)
  319. #
  320. callee_only = False
  321. floats = False
  322. if self._regalloc is not None:
  323. for reg in self._regalloc.rm.reg_bindings.values():
  324. if reg not in self._regalloc.rm.save_around_call_regs:
  325. break
  326. else:
  327. callee_only = True
  328. if self._regalloc.vfprm.reg_bindings:
  329. floats = True
  330. cond_call_adr = self.cond_call_slowpath[floats * 2 + callee_only]
  331. self.mc.BL(cond_call_adr)
  332. self.pop_gcmap(self.mc)
  333. # never any result value
  334. cond = c.get_opposite_of(self.guard_success_cc)
  335. self.guard_success_cc = c.cond_none
  336. pmc = OverwritingBuilder(self.mc, jmp_adr, WORD)
  337. pmc.B_offs(self.mc.currpos(), cond)
  338. # might be overridden again to skip over the following
  339. # guard_no_exception too
  340. self.previous_cond_call_jcond = jmp_adr, cond
  341. return fcond
  342. def emit_op_jump(self, op, arglocs, regalloc, fcond):
  343. target_token = op.getdescr()
  344. assert isinstance(target_token, TargetToken)
  345. target = target_token._ll_loop_code
  346. assert fcond == c.AL
  347. if target_token in self.target_tokens_currently_compiling:
  348. self.mc.B_offs(target, fcond)
  349. else:
  350. self.mc.B(target, fcond)
  351. return fcond
  352. def emit_op_finish(self, op, arglocs, regalloc, fcond):
  353. base_ofs = self.cpu.get_baseofs_of_frame_field()
  354. if len(arglocs) > 0:
  355. [return_val] = arglocs
  356. self.store_reg(self.mc, return_val, r.fp, base_ofs)
  357. ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
  358. faildescrindex = self.get_gcref_from_faildescr(op.getdescr())
  359. self.load_from_gc_table(r.ip.value, faildescrindex)
  360. # XXX self.mov(fail_descr_loc, RawStackLoc(ofs))
  361. self.store_reg(self.mc, r.ip, r.fp, ofs, helper=r.lr)
  362. if op.numargs() > 0 and op.getarg(0).type == REF:
  363. if self._finish_gcmap:
  364. # we're returning with a guard_not_forced_2, and
  365. # additionally we need to say that r0 contains
  366. # a reference too:
  367. self._finish_gcmap[0] |= r_uint(1)
  368. gcmap = self._finish_gcmap
  369. else:
  370. gcmap = self.gcmap_for_finish
  371. self.push_gcmap(self.mc, gcmap, store=True)
  372. elif self._finish_gcmap:
  373. # we're returning with a guard_not_forced_2
  374. gcmap = self._finish_gcmap
  375. self.push_gcmap(self.mc, gcmap, store=True)
  376. else:
  377. # note that the 0 here is redundant, but I would rather
  378. # keep that one and kill all the others
  379. ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
  380. self.mc.gen_load_int(r.ip.value, 0)
  381. self.store_reg(self.mc, r.ip, r.fp, ofs)
  382. self.mc.MOV_rr(r.r0.value, r.fp.value)
  383. # exit function
  384. self.gen_func_epilog()
  385. return fcond
  386. def _genop_call(self, op, arglocs, regalloc, fcond):
  387. return self._emit_call(op, arglocs, fcond=fcond)
  388. emit_op_call_i = _genop_call
  389. emit_op_call_r = _genop_call
  390. emit_op_call_f = _genop_call
  391. emit_op_call_n = _genop_call
  392. def _emit_call(self, op, arglocs, is_call_release_gil=False, fcond=c.AL):
  393. # args = [resloc, size, sign, args...]
  394. from rpython.jit.backend.llsupport.descr import CallDescr
  395. func_index = 3 + is_call_release_gil
  396. cb = callbuilder.get_callbuilder(self.cpu, self, arglocs[func_index],
  397. arglocs[func_index+1:], arglocs[0])
  398. descr = op.getdescr()
  399. assert isinstance(descr, CallDescr)
  400. cb.callconv = descr.get_call_conv()
  401. cb.argtypes = descr.get_arg_types()
  402. cb.restype = descr.get_result_type()
  403. sizeloc = arglocs[1]
  404. assert sizeloc.is_imm()
  405. cb.ressize = sizeloc.value
  406. signloc = arglocs[2]
  407. assert signloc.is_imm()
  408. cb.ressign = signloc.value
  409. if is_call_release_gil:
  410. saveerrloc = arglocs[3]
  411. assert saveerrloc.is_imm()
  412. cb.emit_call_release_gil(saveerrloc.value)
  413. else:
  414. effectinfo = descr.get_extra_info()
  415. if effectinfo is None or effectinfo.check_can_collect():
  416. cb.emit()
  417. else:
  418. cb.emit_no_collect()
  419. return fcond
  420. def _genop_same_as(self, op, arglocs, regalloc, fcond):
  421. argloc, resloc = arglocs
  422. if argloc is not resloc:
  423. self.mov_loc_loc(argloc, resloc)
  424. return fcond
  425. emit_op_same_as_i = _genop_same_as
  426. emit_op_same_as_r = _genop_same_as
  427. emit_op_same_as_f = _genop_same_as
  428. emit_op_cast_ptr_to_int = _genop_same_as
  429. emit_op_cast_int_to_ptr = _genop_same_as
  430. def emit_op_guard_no_exception(self, op, arglocs, regalloc, fcond):
  431. loc = arglocs[0]
  432. failargs = arglocs[1:]
  433. self.mc.LDR_ri(loc.value, loc.value)
  434. self.mc.CMP_ri(loc.value, 0)
  435. self.guard_success_cc = c.EQ
  436. fcond = self._emit_guard(op, failargs)
  437. # If the previous operation was a COND_CALL, overwrite its conditional
  438. # jump to jump over this GUARD_NO_EXCEPTION as well, if we can
  439. if self._find_nearby_operation(-1).getopnum() == rop.COND_CALL:
  440. jmp_adr, prev_cond = self.previous_cond_call_jcond
  441. pmc = OverwritingBuilder(self.mc, jmp_adr, WORD)
  442. pmc.B_offs(self.mc.currpos(), prev_cond)
  443. return fcond
  444. def emit_op_guard_exception(self, op, arglocs, regalloc, fcond):
  445. loc, loc1, resloc, pos_exc_value, pos_exception = arglocs[:5]
  446. failargs = arglocs[5:]
  447. self.mc.gen_load_int(loc1.value, pos_exception.value)
  448. self.mc.LDR_ri(r.ip.value, loc1.value)
  449. self.mc.CMP_rr(r.ip.value, loc.value)
  450. self.guard_success_cc = c.EQ
  451. self._emit_guard(op, failargs)
  452. self._store_and_reset_exception(self.mc, resloc)
  453. return fcond
  454. def emit_op_save_exc_class(self, op, arglocs, regalloc, fcond):
  455. resloc = arglocs[0]
  456. self.mc.gen_load_int(r.ip.value, self.cpu.pos_exception())
  457. self.load_reg(self.mc, resloc, r.ip)
  458. return fcond
  459. def emit_op_save_exception(self, op, arglocs, regalloc, fcond):
  460. resloc = arglocs[0]
  461. self._store_and_reset_exception(self.mc, resloc)
  462. return fcond
  463. def emit_op_restore_exception(self, op, arglocs, regalloc, fcond):
  464. self._restore_exception(self.mc, arglocs[1], arglocs[0])
  465. return fcond
  466. def emit_op_debug_merge_point(self, op, arglocs, regalloc, fcond):
  467. return fcond
  468. emit_op_jit_debug = emit_op_debug_merge_point
  469. emit_op_keepalive = emit_op_debug_merge_point
  470. emit_op_enter_portal_frame = emit_op_debug_merge_point
  471. emit_op_leave_portal_frame = emit_op_debug_merge_point
  472. def emit_op_cond_call_gc_wb(self, op, arglocs, regalloc, fcond):
  473. self._write_barrier_fastpath(self.mc, op.getdescr(), arglocs, fcond)
  474. return fcond
  475. def emit_op_cond_call_gc_wb_array(self, op, arglocs, regalloc, fcond):
  476. self._write_barrier_fastpath(self.mc, op.getdescr(), arglocs,
  477. fcond, array=True)
  478. return fcond
  479. def _write_barrier_fastpath(self, mc, descr, arglocs, fcond=c.AL, array=False,
  480. is_frame=False):
  481. # Write code equivalent to write_barrier() in the GC: it checks
  482. # a flag in the object at arglocs[0], and if set, it calls a
  483. # helper piece of assembler. The latter saves registers as needed
  484. # and call the function remember_young_pointer() from the GC.
  485. if we_are_translated():
  486. cls = self.cpu.gc_ll_descr.has_write_barrier_class()
  487. assert cls is not None and isinstance(descr, cls)
  488. #
  489. card_marking = False
  490. mask = descr.jit_wb_if_flag_singlebyte
  491. if array and descr.jit_wb_cards_set != 0:
  492. # assumptions the rest of the function depends on:
  493. assert (descr.jit_wb_cards_set_byteofs ==
  494. descr.jit_wb_if_flag_byteofs)
  495. assert descr.jit_wb_cards_set_singlebyte == -0x80
  496. card_marking = True
  497. mask = descr.jit_wb_if_flag_singlebyte | -0x80
  498. #
  499. loc_base = arglocs[0]
  500. if is_frame:
  501. assert loc_base is r.fp
  502. mc.LDRB_ri(r.ip.value, loc_base.value,
  503. imm=descr.jit_wb_if_flag_byteofs)
  504. mask &= 0xFF
  505. mc.TST_ri(r.ip.value, imm=mask)
  506. jz_location = mc.currpos()
  507. mc.BKPT()
  508. # for cond_call_gc_wb_array, also add another fast path:
  509. # if GCFLAG_CARDS_SET, then we can just set one bit and be done
  510. if card_marking:
  511. # GCFLAG_CARDS_SET is in this byte at 0x80
  512. mc.TST_ri(r.ip.value, imm=0x80)
  513. js_location = mc.currpos()
  514. mc.BKPT()
  515. else:
  516. js_location = 0
  517. # Write only a CALL to the helper prepared in advance, passing it as
  518. # argument the address of the structure we are writing into
  519. # (the first argument to COND_CALL_GC_WB).
  520. helper_num = card_marking
  521. if is_frame:
  522. helper_num = 4
  523. elif self._regalloc is not None and self._regalloc.vfprm.reg_bindings:
  524. helper_num += 2
  525. if self.wb_slowpath[helper_num] == 0: # tests only
  526. assert not we_are_translated()
  527. self.cpu.gc_ll_descr.write_barrier_descr = descr
  528. self._build_wb_slowpath(card_marking,
  529. bool(self._regalloc.vfprm.reg_bindings))
  530. assert self.wb_slowpath[helper_num] != 0
  531. #
  532. if loc_base is not r.r0:
  533. # push two registers to keep stack aligned
  534. mc.PUSH([r.r0.value, loc_base.value])
  535. mc.MOV_rr(r.r0.value, loc_base.value)
  536. if is_frame:
  537. assert loc_base is r.fp
  538. mc.BL(self.wb_slowpath[helper_num])
  539. if loc_base is not r.r0:
  540. mc.POP([r.r0.value, loc_base.value])
  541. if card_marking:
  542. # The helper ends again with a check of the flag in the object. So
  543. # here, we can simply write again a conditional jump, which will be
  544. # taken if GCFLAG_CARDS_SET is still not set.
  545. jns_location = mc.currpos()
  546. mc.BKPT()
  547. #
  548. # patch the JS above
  549. offset = mc.currpos()
  550. pmc = OverwritingBuilder(mc, js_location, WORD)
  551. pmc.B_offs(offset, c.NE) # We want to jump if the z flag isn't set
  552. #
  553. # case GCFLAG_CARDS_SET: emit a few instructions to do
  554. # directly the card flag setting
  555. loc_index = arglocs[1]
  556. assert loc_index.is_core_reg()
  557. # must save the register loc_index before it is mutated
  558. mc.PUSH([loc_index.value])
  559. tmp1 = loc_index
  560. tmp2 = arglocs[-1] # the last item is a preallocated tmp
  561. # lr = byteofs
  562. s = 3 + descr.jit_wb_card_page_shift
  563. mc.MVN_rr(r.lr.value, loc_index.value,
  564. imm=s, shifttype=shift.LSR)
  565. # tmp1 = byte_index
  566. mc.MOV_ri(r.ip.value, imm=7)
  567. mc.AND_rr(tmp1.value, r.ip.value, loc_index.value,
  568. imm=descr.jit_wb_card_page_shift, shifttype=shift.LSR)
  569. # set the bit
  570. mc.MOV_ri(tmp2.value, imm=1)
  571. mc.LDRB_rr(r.ip.value, loc_base.value, r.lr.value)
  572. mc.ORR_rr_sr(r.ip.value, r.ip.value, tmp2.value,
  573. tmp1.value, shifttype=shift.LSL)
  574. mc.STRB_rr(r.ip.value, loc_base.value, r.lr.value)
  575. # done
  576. mc.POP([loc_index.value])
  577. #
  578. #
  579. # patch the JNS above
  580. offset = mc.currpos()
  581. pmc = OverwritingBuilder(mc, jns_location, WORD)
  582. pmc.B_offs(offset, c.EQ) # We want to jump if the z flag is set
  583. offset = mc.currpos()
  584. pmc = OverwritingBuilder(mc, jz_location, WORD)
  585. pmc.B_offs(offset, c.EQ)
  586. return fcond
  587. def emit_op_gc_store(self, op, arglocs, regalloc, fcond):
  588. value_loc, base_loc, ofs_loc, size_loc = arglocs
  589. scale = get_scale(size_loc.value)
  590. self._write_to_mem(value_loc, base_loc, ofs_loc, imm(scale), fcond)
  591. return fcond
  592. def _emit_op_gc_load(self, op, arglocs, regalloc, fcond):
  593. base_loc, ofs_loc, res_loc, nsize_loc = arglocs
  594. nsize = nsize_loc.value
  595. signed = (nsize < 0)
  596. scale = get_scale(abs(nsize))
  597. self._load_from_mem(res_loc, base_loc, ofs_loc, imm(scale),
  598. signed, fcond)
  599. return fcond
  600. emit_op_gc_load_i = _emit_op_gc_load
  601. emit_op_gc_load_r = _emit_op_gc_load
  602. emit_op_gc_load_f = _emit_op_gc_load
  603. def emit_op_increment_debug_counter(self, op, arglocs, regalloc, fcond):
  604. base_loc, value_loc = arglocs
  605. self.mc.LDR_ri(value_loc.value, base_loc.value, 0, cond=fcond)
  606. self.mc.ADD_ri(value_loc.value, value_loc.value, 1, cond=fcond)
  607. self.mc.STR_ri(value_loc.value, base_loc.value, 0, cond=fcond)
  608. return fcond
  609. def emit_op_gc_store_indexed(self, op, arglocs, regalloc, fcond):
  610. value_loc, base_loc, index_loc, size_loc, ofs_loc = arglocs
  611. assert index_loc.is_core_reg()
  612. # add the base offset
  613. if ofs_loc.value > 0:
  614. self.mc.ADD_ri(r.ip.value, index_loc.value, imm=ofs_loc.value)
  615. index_loc = r.ip
  616. scale = get_scale(size_loc.value)
  617. self._write_to_mem(value_loc, base_loc, index_loc, imm(scale), fcond)
  618. return fcond
  619. def _write_to_mem(self, value_loc, base_loc, ofs_loc, scale, fcond=c.AL):
  620. # Write a value of size '1 << scale' at the address
  621. # 'base_ofs + ofs_loc'. Note that 'scale' is not used to scale
  622. # the offset!
  623. if scale.value == 3:
  624. assert value_loc.is_vfp_reg()
  625. # vstr only supports imm offsets
  626. # so if the ofset is too large we add it to the base and use an
  627. # offset of 0
  628. if ofs_loc.is_core_reg():
  629. tmploc, save = self.get_tmp_reg([value_loc, base_loc, ofs_loc])
  630. assert not save
  631. self.mc.ADD_rr(tmploc.value, base_loc.value, ofs_loc.value)
  632. base_loc = tmploc
  633. ofs_loc = imm(0)
  634. else:
  635. assert ofs_loc.is_imm()
  636. assert ofs_loc.value % 4 == 0
  637. self.mc.VSTR(value_loc.value, base_loc.value, ofs_loc.value)
  638. elif scale.value == 2:
  639. if ofs_loc.is_imm():
  640. self.mc.STR_ri(value_loc.value, base_loc.value,
  641. ofs_loc.value, cond=fcond)
  642. else:
  643. self.mc.STR_rr(value_loc.value, base_loc.value,
  644. ofs_loc.value, cond=fcond)
  645. elif scale.value == 1:
  646. if ofs_loc.is_imm():
  647. self.mc.STRH_ri(value_loc.value, base_loc.value,
  648. ofs_loc.value, cond=fcond)
  649. else:
  650. self.mc.STRH_rr(value_loc.value, base_loc.value,
  651. ofs_loc.value, cond=fcond)
  652. elif scale.value == 0:
  653. if ofs_loc.is_imm():
  654. self.mc.STRB_ri(value_loc.value, base_loc.value,
  655. ofs_loc.value, cond=fcond)
  656. else:
  657. self.mc.STRB_rr(value_loc.value, base_loc.value,
  658. ofs_loc.value, cond=fcond)
  659. else:
  660. assert 0
  661. def _emit_op_gc_load_indexed(self, op, arglocs, regalloc, fcond):
  662. res_loc, base_loc, index_loc, nsize_loc, ofs_loc = arglocs
  663. assert index_loc.is_core_reg()
  664. nsize = nsize_loc.value
  665. signed = (nsize < 0)
  666. # add the base offset
  667. if ofs_loc.value > 0:
  668. self.mc.ADD_ri(r.ip.value, index_loc.value, imm=ofs_loc.value)
  669. index_loc = r.ip
  670. #
  671. scale = get_scale(abs(nsize))
  672. self._load_from_mem(res_loc, base_loc, index_loc, imm(scale),
  673. signed, fcond)
  674. return fcond
  675. emit_op_gc_load_indexed_i = _emit_op_gc_load_indexed
  676. emit_op_gc_load_indexed_r = _emit_op_gc_load_indexed
  677. emit_op_gc_load_indexed_f = _emit_op_gc_load_indexed
  678. def _load_from_mem(self, res_loc, base_loc, ofs_loc, scale,
  679. signed=False, fcond=c.AL):
  680. # Load a value of '1 << scale' bytes, from the memory location
  681. # 'base_loc + ofs_loc'. Note that 'scale' is not used to scale
  682. # the offset!
  683. #
  684. if scale.value == 3:
  685. assert res_loc.is_vfp_reg()
  686. # vldr only supports imm offsets
  687. # if the offset is in a register we add it to the base and use a
  688. # tmp reg
  689. if ofs_loc.is_core_reg():
  690. tmploc, save = self.get_tmp_reg([base_loc, ofs_loc])
  691. assert not save
  692. self.mc.ADD_rr(tmploc.value, base_loc.value, ofs_loc.value)
  693. base_loc = tmploc
  694. ofs_loc = imm(0)
  695. else:
  696. assert ofs_loc.is_imm()
  697. assert ofs_loc.value % 4 == 0
  698. self.mc.VLDR(res_loc.value, base_loc.value, ofs_loc.value, cond=fcond)
  699. elif scale.value == 2:
  700. if ofs_loc.is_imm():
  701. self.mc.LDR_ri(res_loc.value, base_loc.value,
  702. ofs_loc.value, cond=fcond)
  703. else:
  704. self.mc.LDR_rr(res_loc.value, base_loc.value,
  705. ofs_loc.value, cond=fcond)
  706. elif scale.value == 1:
  707. if ofs_loc.is_imm():
  708. if signed:
  709. self.mc.LDRSH_ri(res_loc.value, base_loc.value,
  710. ofs_loc.value, cond=fcond)
  711. else:
  712. self.mc.LDRH_ri(res_loc.value, base_loc.value,
  713. ofs_loc.value, cond=fcond)
  714. else:
  715. if signed:
  716. self.mc.LDRSH_rr(res_loc.value, base_loc.value,
  717. ofs_loc.value, cond=fcond)
  718. else:
  719. self.mc.LDRH_rr(res_loc.value, base_loc.value,
  720. ofs_loc.value, cond=fcond)
  721. elif scale.value == 0:
  722. if ofs_loc.is_imm():
  723. if signed:
  724. self.mc.LDRSB_ri(res_loc.value, base_loc.value,
  725. ofs_loc.value, cond=fcond)
  726. else:
  727. self.mc.LDRB_ri(res_loc.value, base_loc.value,
  728. ofs_loc.value, cond=fcond)
  729. else:
  730. if signed:
  731. self.mc.LDRSB_rr(res_loc.value, base_loc.value,
  732. ofs_loc.value, cond=fcond)
  733. else:
  734. self.mc.LDRB_rr(res_loc.value, base_loc.value,
  735. ofs_loc.value, cond=fcond)
  736. else:
  737. assert 0
  738. #from ../x86/regalloc.py:928 ff.
  739. def emit_op_copystrcontent(self, op, arglocs, regalloc, fcond):
  740. assert len(arglocs) == 0
  741. self._emit_copystrcontent(op, regalloc, fcond, is_unicode=False)
  742. return fcond
  743. def emit_op_copyunicodecontent(self, op, arglocs, regalloc, fcond):
  744. assert len(arglocs) == 0
  745. self._emit_copystrcontent(op, regalloc, fcond, is_unicode=True)
  746. return fcond
  747. def _emit_copystrcontent(self, op, regalloc, fcond, is_unicode):
  748. # compute the source address
  749. args = op.getarglist()
  750. base_loc = regalloc.rm.make_sure_var_in_reg(args[0], args)
  751. ofs_loc = regalloc.rm.make_sure_var_in_reg(args[2], args)
  752. assert args[0] is not args[1] # forbidden case of aliasing
  753. srcaddr_box = TempVar()
  754. forbidden_vars = [args[1], args[3], args[4], srcaddr_box]
  755. srcaddr_loc = regalloc.rm.force_allocate_reg(srcaddr_box, forbidden_vars)
  756. self._gen_address_inside_string(base_loc, ofs_loc, srcaddr_loc,
  757. is_unicode=is_unicode)
  758. # compute the destination address
  759. base_loc = regalloc.rm.make_sure_var_in_reg(args[1], forbidden_vars)
  760. ofs_loc = regalloc.rm.make_sure_var_in_reg(args[3], forbidden_vars)
  761. forbidden_vars = [args[4], srcaddr_box]
  762. dstaddr_box = TempVar()
  763. dstaddr_loc = regalloc.rm.force_allocate_reg(dstaddr_box, forbidden_vars)
  764. self._gen_address_inside_string(base_loc, ofs_loc, dstaddr_loc,
  765. is_unicode=is_unicode)
  766. # compute the length in bytes
  767. length_box = args[4]
  768. length_loc = regalloc.loc(length_box)
  769. if is_unicode:
  770. forbidden_vars = [srcaddr_box, dstaddr_box]
  771. bytes_box = TempVar()
  772. bytes_loc = regalloc.rm.force_allocate_reg(bytes_box, forbidden_vars)
  773. scale = self._get_unicode_item_scale()
  774. if not length_loc.is_core_reg():
  775. self.regalloc_mov(length_loc, bytes_loc)
  776. length_loc = bytes_loc
  777. assert length_loc.is_core_reg()
  778. self.mc.MOV_ri(r.ip.value, 1 << scale)
  779. self.mc.MUL(bytes_loc.value, r.ip.value, length_loc.value)
  780. length_box = bytes_box
  781. length_loc = bytes_loc
  782. # call memcpy()
  783. regalloc.before_call()
  784. self.simple_call_no_collect(imm(self.memcpy_addr),
  785. [dstaddr_loc, srcaddr_loc, length_loc])
  786. regalloc.rm.possibly_free_var(length_box)
  787. regalloc.rm.possibly_free_var(dstaddr_box)
  788. regalloc.rm.possibly_free_var(srcaddr_box)
  789. def _gen_address_inside_string(self, baseloc, ofsloc, resloc, is_unicode):
  790. if is_unicode:
  791. ofs_items, _, _ = symbolic.get_array_token(rstr.UNICODE,
  792. self.cpu.translate_support_code)
  793. scale = self._get_unicode_item_scale()
  794. else:
  795. ofs_items, itemsize, _ = symbolic.get_array_token(rstr.STR,
  796. self.cpu.translate_support_code)
  797. assert itemsize == 1
  798. ofs_items -= 1 # for the extra null character
  799. scale = 0
  800. self._gen_address(resloc, baseloc, ofsloc, scale, ofs_items)
  801. # result = base_loc + (scaled_loc << scale) + static_offset
  802. def _gen_address(self, result, base_loc, scaled_loc, scale=0, static_offset=0):
  803. assert scaled_loc.is_core_reg()
  804. assert base_loc.is_core_reg()
  805. assert check_imm_arg(scale)
  806. assert check_imm_arg(static_offset)
  807. if scale > 0:
  808. self.mc.LSL_ri(r.ip.value, scaled_loc.value, scale)
  809. scaled_loc = r.ip
  810. else:
  811. scaled_loc = scaled_loc
  812. self.mc.ADD_rr(result.value, base_loc.value, scaled_loc.value)
  813. self.mc.ADD_ri(result.value, result.value, static_offset)
  814. def _get_unicode_item_scale(self):
  815. _, itemsize, _ = symbolic.get_array_token(rstr.UNICODE,
  816. self.cpu.translate_support_code)
  817. if itemsize == 4:
  818. return 2
  819. elif itemsize == 2:
  820. return 1
  821. else:
  822. raise AssertionError("bad unicode item size")
  823. def store_force_descr(self, op, fail_locs, frame_depth):
  824. pos = self.mc.currpos()
  825. guard_token = self.build_guard_token(op, frame_depth, fail_locs, pos, c.AL)
  826. #self.pending_guards.append(guard_token)
  827. self._finish_gcmap = guard_token.gcmap
  828. self._store_force_index(op)
  829. self.store_info_on_descr(pos, guard_token)
  830. def emit_op_force_token(self, op, arglocs, regalloc, fcond):
  831. # XXX kill me
  832. res_loc = arglocs[0]
  833. self.mc.MOV_rr(res_loc.value, r.fp.value)
  834. return fcond
  835. def imm(self, v):
  836. return imm(v)
  837. def _genop_call_assembler(self, op, arglocs, regalloc, fcond):
  838. if len(arglocs) == 4:
  839. [argloc, vloc, result_loc, tmploc] = arglocs
  840. else:
  841. [argloc, result_loc, tmploc] = arglocs
  842. vloc = imm(0)
  843. self._store_force_index(self._find_nearby_operation(+1))
  844. self.call_assembler(op, argloc, vloc, result_loc, tmploc)
  845. return fcond
  846. emit_op_call_assembler_i = _genop_call_assembler
  847. emit_op_call_assembler_r = _genop_call_assembler
  848. emit_op_call_assembler_f = _genop_call_assembler
  849. emit_op_call_assembler_n = _genop_call_assembler
  850. def _call_assembler_emit_call(self, addr, argloc, resloc):
  851. ofs = self.saved_threadlocal_addr
  852. threadlocal_loc = RawSPStackLocation(ofs, INT)
  853. self.simple_call(addr, [argloc, threadlocal_loc], result_loc=resloc)
  854. def _call_assembler_emit_helper_call(self, addr, arglocs, resloc):
  855. self.simple_call(addr, arglocs, result_loc=resloc)
  856. def _call_assembler_check_descr(self, value, tmploc):
  857. ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
  858. self.mc.LDR_ri(r.ip.value, tmploc.value, imm=ofs)
  859. if check_imm_arg(value):
  860. self.mc.CMP_ri(r.ip.value, imm=value)
  861. else:
  862. self.mc.gen_load_int(r.lr.value, value)
  863. self.mc.CMP_rr(r.ip.value, r.lr.value)
  864. pos = self.mc.currpos()
  865. self.mc.BKPT()
  866. return pos
  867. def _call_assembler_patch_je(self, result_loc, jmp_location):
  868. pos = self.mc.currpos()
  869. self.mc.BKPT()
  870. #
  871. pmc = OverwritingBuilder(self.mc, jmp_location, WORD)
  872. pmc.B_offs(self.mc.currpos(), c.EQ)
  873. return pos
  874. def _call_assembler_load_result(self, op, result_loc):
  875. if op.type != 'v':
  876. # load the return value from (tmploc, 0)
  877. kind = op.type
  878. descr = self.cpu.getarraydescr_for_frame(kind)
  879. if kind == FLOAT:
  880. ofs = self.cpu.unpack_arraydescr(descr)
  881. assert check_imm_arg(ofs)
  882. assert result_loc.is_vfp_reg()
  883. # we always have a register here, since we have to sync them
  884. # before call_assembler
  885. self.load_reg(self.mc, result_loc, r.r0, ofs=ofs)
  886. else:
  887. assert result_loc is r.r0
  888. ofs = self.cpu.unpack_arraydescr(descr)
  889. assert check_imm_arg(ofs)
  890. self.mc.LDR_ri(result_loc.value, result_loc.value, imm=ofs)
  891. def _call_assembler_patch_jmp(self, jmp_location):
  892. # merge point
  893. currpos = self.mc.currpos()
  894. pmc = OverwritingBuilder(self.mc, jmp_location, WORD)
  895. pmc.B_offs(currpos)
  896. # ../x86/assembler.py:668
  897. def redirect_call_assembler(self, oldlooptoken, newlooptoken):
  898. # some minimal sanity checking
  899. old_nbargs = oldlooptoken.compiled_loop_token._debug_nbargs
  900. new_nbargs = newlooptoken.compiled_loop_token._debug_nbargs
  901. assert old_nbargs == new_nbargs
  902. # we overwrite the instructions at the old _ll_function_addr
  903. # to start with a JMP to the new _ll_function_addr.
  904. # Ideally we should rather patch all existing CALLs, but well.
  905. oldadr = oldlooptoken._ll_function_addr
  906. target = newlooptoken._ll_function_addr
  907. # copy frame-info data
  908. baseofs = self.cpu.get_baseofs_of_frame_field()
  909. newlooptoken.compiled_loop_token.update_frame_info(
  910. oldlooptoken.compiled_loop_token, baseofs)
  911. mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
  912. mc.B(target)
  913. mc.copy_to_raw_memory(oldadr)
  914. def emit_op_guard_not_forced(self, op, arglocs, regalloc, fcond):
  915. ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
  916. self.mc.LDR_ri(r.ip.value, r.fp.value, imm=ofs)
  917. self.mc.CMP_ri(r.ip.value, 0)
  918. self.guard_success_cc = c.EQ
  919. self._emit_guard(op, arglocs)
  920. return fcond
  921. def _genop_call_may_force(self, op, arglocs, regalloc, fcond):
  922. self._store_force_index(self._find_nearby_operation(+1))
  923. self._emit_call(op, arglocs, fcond=fcond)
  924. return fcond
  925. emit_op_call_may_force_i = _genop_call_may_force
  926. emit_op_call_may_force_r = _genop_call_may_force
  927. emit_op_call_may_force_f = _genop_call_may_force
  928. emit_op_call_may_force_n = _genop_call_may_force
  929. def _genop_call_release_gil(self, op, arglocs, regalloc, fcond):
  930. self._store_force_index(self._find_nearby_operation(+1))
  931. self._emit_call(op, arglocs, is_call_release_gil=True)
  932. return fcond
  933. emit_op_call_release_gil_i = _genop_call_release_gil
  934. emit_op_call_release_gil_f = _genop_call_release_gil
  935. emit_op_call_release_gil_n = _genop_call_release_gil
  936. def _store_force_index(self, guard_op):
  937. assert (guard_op.getopnum() == rop.GUARD_NOT_FORCED or
  938. guard_op.getopnum() == rop.GUARD_NOT_FORCED_2)
  939. faildescr = guard_op.getdescr()
  940. faildescrindex = self.get_gcref_from_faildescr(faildescr)
  941. ofs = self.cpu.get_ofs_of_frame_field('jf_force_descr')
  942. self.load_from_gc_table(r.ip.value, faildescrindex)
  943. self.store_reg(self.mc, r.ip, r.fp, ofs)
  944. def _find_nearby_operation(self, delta):
  945. regalloc = self._regalloc
  946. return regalloc.operations[regalloc.rm.position + delta]
  947. def emit_op_check_memory_error(self, op, arglocs, regalloc, fcond):
  948. self.propagate_memoryerror_if_reg_is_null(arglocs[0])
  949. self._alignment_check()
  950. return fcond
  951. def _alignment_check(self):
  952. if not self.debug:
  953. return
  954. self.mc.MOV_rr(r.ip.value, r.r0.value)
  955. self.mc.AND_ri(r.ip.value, r.ip.value, 3)
  956. self.mc.CMP_ri(r.ip.value, 0)
  957. self.mc.MOV_rr(r.pc.value, r.pc.value, cond=c.EQ)
  958. self.mc.BKPT()
  959. self.mc.NOP()
  960. emit_op_float_add = gen_emit_float_op('float_add', 'VADD')
  961. emit_op_float_sub = gen_emit_float_op('float_sub', 'VSUB')
  962. emit_op_float_mul = gen_emit_float_op('float_mul', 'VMUL')
  963. emit_op_float_truediv = gen_emit_float_op('float_truediv', 'VDIV')
  964. emit_op_float_neg = gen_emit_unary_float_op('float_neg', 'VNEG')
  965. emit_op_float_abs = gen_emit_unary_float_op('float_abs', 'VABS')
  966. emit_opx_math_sqrt = gen_emit_unary_float_op('math_sqrt', 'VSQRT')
  967. emit_op_float_lt = gen_emit_float_cmp_op('float_lt', c.VFP_LT)
  968. emit_op_float_le = gen_emit_float_cmp_op('float_le', c.VFP_LE)
  969. emit_op_float_eq = gen_emit_float_cmp_op('float_eq', c.EQ)
  970. emit_op_float_ne = gen_emit_float_cmp_op('float_ne', c.NE)
  971. emit_op_float_gt = gen_emit_float_cmp_op('float_gt', c.GT)
  972. emit_op_float_ge = gen_emit_float_cmp_op('float_ge', c.GE)
  973. def emit_op_cast_float_to_int(self, op, arglocs, regalloc, fcond):
  974. arg, res = arglocs
  975. assert arg.is_vfp_reg()
  976. assert res.is_core_reg()
  977. self.mc.VCVT_float_to_int(r.svfp_ip.value, arg.value)
  978. self.mc.VMOV_sc(res.value, r.svfp_ip.value)
  979. return fcond
  980. def emit_op_cast_int_to_float(self, op, arglocs, regalloc, fcond):
  981. arg, res = arglocs
  982. assert res.is_vfp_reg()
  983. assert arg.is_core_reg()
  984. self.mc.VMOV_cs(r.svfp_ip.value, arg.value)
  985. self.mc.VCVT_int_to_float(res.value, r.svfp_ip.value)
  986. return fcond
  987. # the following five instructions are only ARMv7 with NEON;
  988. # regalloc.py won't call them at all, in other cases
  989. emit_opx_llong_add = gen_emit_float_op('llong_add', 'VADD_i64')
  990. emit_opx_llong_sub = gen_emit_float_op('llong_sub', 'VSUB_i64')
  991. emit_opx_llong_and = gen_emit_float_op('llong_and', 'VAND_i64')
  992. emit_opx_llong_or = gen_emit_float_op('llong_or', 'VORR_i64')
  993. emit_opx_llong_xor = gen_emit_float_op('llong_xor', 'VEOR_i64')
  994. def emit_opx_llong_to_int(self, op, arglocs, regalloc, fcond):
  995. loc = arglocs[0]
  996. res = arglocs[1]
  997. assert loc.is_vfp_reg()
  998. assert res.is_core_reg()
  999. self.mc.VMOV_rc(res.value, r.ip.value, loc.value)
  1000. return fcond
  1001. emit_op_convert_float_bytes_to_longlong = gen_emit_unary_float_op(
  1002. 'float_bytes_to_longlong', 'VMOV_cc')
  1003. emit_op_convert_longlong_bytes_to_float = gen_emit_unary_float_op(
  1004. 'longlong_bytes_to_float', 'VMOV_cc')
  1005. """ disabled: missing an implementation that works in user mode
  1006. def ..._read_timestamp(...):
  1007. tmp = arglocs[0]
  1008. res = arglocs[1]
  1009. self.mc.MRC(15, 0, tmp.value, 15, 12, 1)
  1010. self.mc.MOV_ri(r.ip.value, 0)
  1011. self.mc.VMOV_cr(res.value, tmp.value, r.ip.value)
  1012. return fcond
  1013. """
  1014. def emit_op_cast_float_to_singlefloat(self, op, arglocs, regalloc, fcond):
  1015. arg, res = arglocs
  1016. assert arg.is_vfp_reg()
  1017. assert res.is_core_reg()
  1018. self.mc.VCVT_f64_f32(r.svfp_ip.value, arg.value)
  1019. self.mc.VMOV_sc(res.value, r.svfp_ip.value)
  1020. return fcond
  1021. def emit_op_cast_singlefloat_to_float(self, op, arglocs, regalloc, fcond):
  1022. arg, res = arglocs
  1023. assert res.is_vfp_reg()
  1024. assert arg.is_core_reg()
  1025. self.mc.VMOV_cs(r.svfp_ip.value, arg.value)
  1026. self.mc.VCVT_f32_f64(res.value, r.svfp_ip.value)
  1027. return fcond
  1028. #from ../x86/regalloc.py:1388
  1029. def emit_op_zero_array(self, op, arglocs, regalloc, fcond):
  1030. from rpython.jit.backend.llsupport.descr import unpack_arraydescr
  1031. assert len(arglocs) == 0
  1032. size_box = op.getarg(2)
  1033. if isinstance(size_box, ConstInt) and size_box.getint() == 0:
  1034. return fcond # nothing to do
  1035. itemsize, baseofs, _ = unpack_arraydescr(op.getdescr())
  1036. args = op.getarglist()
  1037. #
  1038. # ZERO_ARRAY(base_loc, start, size, 1, 1)
  1039. # 'start' and 'size' are both expressed in bytes,
  1040. # and the two scaling arguments should always be ConstInt(1) on ARM.
  1041. assert args[3].getint() == 1
  1042. assert args[4].getint() == 1
  1043. #
  1044. base_loc = regalloc.rm.make_sure_var_in_reg(args[0], args)
  1045. startbyte_box = args[1]
  1046. if isinstance(startbyte_box, ConstInt):
  1047. startbyte_loc = None
  1048. startbyte = startbyte_box.getint()
  1049. assert startbyte >= 0
  1050. else:
  1051. startby

Large files files are truncated, but you can click here to view the full file