[pypy-commit] pypy default: unify code that generates memory read instructions
bivab
noreply at buildbot.pypy.org
Sun Jun 2 22:31:02 CEST 2013
Author: David Schneider <david.schneider at picle.org>
Branch:
Changeset: r64720:641e439a5353
Date: 2013-06-02 15:22 -0500
http://bitbucket.org/pypy/pypy/changeset/641e439a5353/
Log: unify code that generates memory read instructions
diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -15,6 +15,7 @@
gen_emit_unary_float_op,
saved_registers)
from rpython.jit.backend.arm.helper.regalloc import check_imm_arg
+from rpython.jit.backend.arm.helper.regalloc import VMEM_imm_size
from rpython.jit.backend.arm.codebuilder import InstrBuilder, OverwritingBuilder
from rpython.jit.backend.arm.jump import remap_frame_layout
from rpython.jit.backend.arm.regalloc import TempBox
@@ -23,6 +24,7 @@
from rpython.jit.backend.llsupport.gcmap import allocate_gcmap
from rpython.jit.backend.llsupport.descr import InteriorFieldDescr
from rpython.jit.backend.llsupport.assembler import GuardToken, BaseAssembler
+from rpython.jit.backend.llsupport.regalloc import get_scale
from rpython.jit.metainterp.history import (Box, AbstractFailDescr,
INT, FLOAT, REF)
from rpython.jit.metainterp.history import TargetToken
@@ -559,47 +561,8 @@
def emit_op_getfield_gc(self, op, arglocs, regalloc, fcond):
base_loc, ofs, res, size = arglocs
signed = op.getdescr().is_field_signed()
- if size.value == 8:
- assert res.is_vfp_reg()
- # vldr only supports imm offsets
- # so if the ofset is too large we add it to the base and use an
- # offset of 0
- if ofs.is_reg():
- self.mc.ADD_rr(r.ip.value, base_loc.value, ofs.value)
- base_loc = r.ip
- ofs = imm(0)
- else:
- assert ofs.value % 4 == 0
- self.mc.VLDR(res.value, base_loc.value, ofs.value)
- elif size.value == 4:
- if ofs.is_imm():
- self.mc.LDR_ri(res.value, base_loc.value, ofs.value)
- else:
- self.mc.LDR_rr(res.value, base_loc.value, ofs.value)
- elif size.value == 2:
- if ofs.is_imm():
- if signed:
- self.mc.LDRSH_ri(res.value, base_loc.value, ofs.value)
- else:
- self.mc.LDRH_ri(res.value, base_loc.value, ofs.value)
- else:
- if signed:
- self.mc.LDRSH_rr(res.value, base_loc.value, ofs.value)
- else:
- self.mc.LDRH_rr(res.value, base_loc.value, ofs.value)
- elif size.value == 1:
- if ofs.is_imm():
- if signed:
- self.mc.LDRSB_ri(res.value, base_loc.value, ofs.value)
- else:
- self.mc.LDRB_ri(res.value, base_loc.value, ofs.value)
- else:
- if signed:
- self.mc.LDRSB_rr(res.value, base_loc.value, ofs.value)
- else:
- self.mc.LDRB_rr(res.value, base_loc.value, ofs.value)
- else:
- assert 0
+ scale = get_scale(size.value)
+ self._load_from_mem(res, base_loc, ofs, imm(scale), signed, fcond)
return fcond
emit_op_getfield_raw = emit_op_getfield_gc
@@ -609,39 +572,22 @@
def emit_op_getinteriorfield_gc(self, op, arglocs, regalloc, fcond):
(base_loc, index_loc, res_loc,
ofs_loc, ofs, itemsize, fieldsize) = arglocs
- self.mc.gen_load_int(r.ip.value, itemsize.value)
- self.mc.MUL(r.ip.value, index_loc.value, r.ip.value)
+ scale = get_scale(fieldsize.value)
+ tmploc, save = self.get_tmp_reg([base_loc, ofs_loc])
+ assert not save
+ self.mc.gen_load_int(tmploc.value, itemsize.value)
+ self.mc.MUL(tmploc.value, index_loc.value, tmploc.value)
descr = op.getdescr()
assert isinstance(descr, InteriorFieldDescr)
signed = descr.fielddescr.is_field_signed()
if ofs.value > 0:
if ofs_loc.is_imm():
- self.mc.ADD_ri(r.ip.value, r.ip.value, ofs_loc.value)
+ self.mc.ADD_ri(tmploc.value, tmploc.value, ofs_loc.value)
else:
- self.mc.ADD_rr(r.ip.value, r.ip.value, ofs_loc.value)
-
- if fieldsize.value == 8:
- # vldr only supports imm offsets
- # so if the ofset is too large we add it to the base and use an
- # offset of 0
- assert res_loc.is_vfp_reg()
- self.mc.ADD_rr(r.ip.value, base_loc.value, r.ip.value)
- self.mc.VLDR(res_loc.value, r.ip.value, 0)
- elif fieldsize.value == 4:
- self.mc.LDR_rr(res_loc.value, base_loc.value, r.ip.value)
- elif fieldsize.value == 2:
- if signed:
- self.mc.LDRSH_rr(res_loc.value, base_loc.value, r.ip.value)
- else:
- self.mc.LDRH_rr(res_loc.value, base_loc.value, r.ip.value)
- elif fieldsize.value == 1:
- if signed:
- self.mc.LDRSB_rr(res_loc.value, base_loc.value, r.ip.value)
- else:
- self.mc.LDRB_rr(res_loc.value, base_loc.value, r.ip.value)
- else:
- assert 0
-
+ self.mc.ADD_rr(tmploc.value, tmploc.value, ofs_loc.value)
+ ofs_loc = tmploc
+ self._load_from_mem(res_loc, base_loc, ofs_loc,
+ imm(scale), signed, fcond)
return fcond
def emit_op_setinteriorfield_gc(self, op, arglocs, regalloc, fcond):
@@ -731,33 +677,73 @@
self.mc.ADD_ri(r.ip.value, ofs_loc.value, imm=ofs.value)
ofs_loc = r.ip
#
- self._load_from_mem(res_loc, base_loc, ofs_loc, scale, signed)
+ self._load_from_mem(res_loc, base_loc, ofs_loc, scale, signed, fcond)
return fcond
def _load_from_mem(self, res_loc, base_loc, ofs_loc, scale,
signed=False, fcond=c.AL):
if scale.value == 3:
assert res_loc.is_vfp_reg()
- assert ofs_loc.is_reg()
- self.mc.ADD_rr(r.ip.value, base_loc.value, ofs_loc.value)
- self.mc.VLDR(res_loc.value, r.ip.value, cond=fcond)
+ # vldr only supports imm offsets
+ # if the offset is in a register we add it to the base and use a
+ # tmp reg
+ if ofs_loc.is_reg():
+ tmploc, save = self.get_tmp_reg([base_loc, ofs_loc])
+ assert not save
+ self.mc.ADD_rr(tmploc.value, base_loc.value, ofs_loc.value)
+ base_loc = tmploc
+ ofs_loc = imm(0)
+ else:
+ assert ofs_loc.is_imm()
+ # if the ofset is too large for an imm we add it to the base and use an
+ # offset of 0
+ if check_imm_arg(ofs_loc.value, VMEM_imm_size):
+ tmploc, save = self.get_tmp_reg([base_loc, ofs_loc])
+ assert not save
+ self.mc.gen_load_int(tmploc.value, ofs_loc.value)
+ self.mc.ADD_rr(tmploc.value, base_loc.value, tmploc.value)
+ base_loc = tmploc
+ ofs_loc = imm(0)
+ else: # sanity check
+ assert ofs_loc.value % 4 == 0
+ self.mc.VLDR(res_loc.value, base_loc.value, ofs_loc.value, cond=fcond)
elif scale.value == 2:
- self.mc.LDR_rr(res_loc.value, base_loc.value,
- ofs_loc.value, cond=fcond)
+ if ofs_loc.is_imm():
+ self.mc.LDR_ri(res_loc.value, base_loc.value,
+ ofs_loc.value, cond=fcond)
+ else:
+ self.mc.LDR_rr(res_loc.value, base_loc.value,
+ ofs_loc.value, cond=fcond)
elif scale.value == 1:
- if signed:
- self.mc.LDRSH_rr(res_loc.value, base_loc.value,
- ofs_loc.value, cond=fcond)
+ if ofs_loc.is_imm():
+ if signed:
+ self.mc.LDRSH_ri(res_loc.value, base_loc.value,
+ ofs_loc.value, cond=fcond)
+ else:
+ self.mc.LDRH_ri(res_loc.value, base_loc.value,
+ ofs_loc.value, cond=fcond)
else:
- self.mc.LDRH_rr(res_loc.value, base_loc.value,
- ofs_loc.value, cond=fcond)
+ if signed:
+ self.mc.LDRSH_rr(res_loc.value, base_loc.value,
+ ofs_loc.value, cond=fcond)
+ else:
+ self.mc.LDRH_rr(res_loc.value, base_loc.value,
+ ofs_loc.value, cond=fcond)
elif scale.value == 0:
- if signed:
- self.mc.LDRSB_rr(res_loc.value, base_loc.value,
- ofs_loc.value, cond=fcond)
+ if ofs_loc.is_imm():
+ if signed:
+ self.mc.LDRSB_ri(res_loc.value, base_loc.value,
+ ofs_loc.value, cond=fcond)
+ else:
+ self.mc.LDRB_ri(res_loc.value, base_loc.value,
+ ofs_loc.value, cond=fcond)
else:
- self.mc.LDRB_rr(res_loc.value, base_loc.value,
- ofs_loc.value, cond=fcond)
+ if signed:
+ self.mc.LDRSB_rr(res_loc.value, base_loc.value,
+ ofs_loc.value, cond=fcond)
+ else:
+ self.mc.LDRB_rr(res_loc.value, base_loc.value,
+ ofs_loc.value, cond=fcond)
else:
assert 0
@@ -770,7 +756,7 @@
# no base offset
assert ofs.value == 0
signed = op.getdescr().is_item_signed()
- self._load_from_mem(res_loc, base_loc, ofs_loc, scale, signed)
+ self._load_from_mem(res_loc, base_loc, ofs_loc, scale, signed, fcond)
return fcond
def emit_op_strlen(self, op, arglocs, regalloc, fcond):
@@ -993,7 +979,7 @@
assert result_loc.is_vfp_reg()
# we always have a register here, since we have to sync them
# before call_assembler
- self.mc.VLDR(result_loc.value, r.r0.value, imm=ofs)
+ self.load_reg(self.mc, result_loc, r.r0, ofs=ofs)
else:
assert result_loc is r.r0
ofs = self.cpu.unpack_arraydescr(descr)
More information about the pypy-commit
mailing list