summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLogan Chien <tzuhsiang.chien@gmail.com>2024-01-28 15:52:19 -0800
committerLogan Chien <tzuhsiang.chien@gmail.com>2024-08-11 20:36:41 -0700
commitf0953f2695185e259f7de6611f3cf1282a5a1a47 (patch)
tree97093b0388f7373cab6d7722ff4e3246add6deea
parentriscv: Emit large int or float in constant pool (diff)
downloadpypy-f0953f2695185e259f7de6611f3cf1282a5a1a47.tar.gz
pypy-f0953f2695185e259f7de6611f3cf1282a5a1a47.tar.bz2
pypy-f0953f2695185e259f7de6611f3cf1282a5a1a47.zip
riscv: Support large frame slot offsets
This commit adds support for large frame slot offsets. Before this commit, the code generator assumes the frame slot offsets is always addressable with signed 12-bit immediate. But, it turns out 12-bit is not enough. `lib_python_tests.py` `test_tarfile` triggers the assertion in the code generator. This commit fixes the problem by emitting `load_imm + ADD` when the immediate is too large for `ADDI`. Test: pypy2.7 testrunner/lib_python_tests.py -v -k test_tarfile
-rw-r--r--rpython/jit/backend/riscv/assembler.py26
-rw-r--r--rpython/jit/backend/riscv/codebuilder.py20
2 files changed, 40 insertions, 6 deletions
diff --git a/rpython/jit/backend/riscv/assembler.py b/rpython/jit/backend/riscv/assembler.py
index 5f6029bba2..3aa4828805 100644
--- a/rpython/jit/backend/riscv/assembler.py
+++ b/rpython/jit/backend/riscv/assembler.py
@@ -1671,9 +1671,11 @@ class AssemblerRISCV(OpAssembler):
def _mov_stack_to_loc(self, prev_loc, loc):
offset = prev_loc.value
if loc.is_core_reg():
- self.mc.load_int(loc.value, r.jfp.value, offset)
+ self.mc.load_int_from_base_plus_offset(loc.value, r.jfp.value,
+ offset)
elif loc.is_fp_reg():
- self.mc.load_float(loc.value, r.jfp.value, offset)
+ self.mc.load_float_from_base_plus_offset(loc.value, r.jfp.value,
+ offset, tmp=r.x31.value)
else:
assert 0, 'unsupported case'
@@ -1681,7 +1683,15 @@ class AssemblerRISCV(OpAssembler):
if loc.is_core_reg():
self.mc.MV(loc.value, prev_loc.value)
elif loc.is_stack():
- self.mc.store_int(prev_loc.value, r.jfp.value, loc.value)
+ # Use `r.shadow_old` as `scratch_reg`. We can't use `r.x31`
+ # because `prev_loc` can be `r.x31` (see also.
+ # `regalloc_prepare_move`). We can't use `r.ra` because `r.ra` is
+ # allocated for the callee function address in `callbuiler.py`
+ # and its lifetime overlaps with `remap_frame_layout`.
+ scratch_reg = r.shadow_old
+ self.mc.store_int_to_base_plus_offset(prev_loc.value, r.jfp.value,
+ loc.value,
+ tmp=scratch_reg.value)
else:
assert 0, 'unsupported case'
@@ -1692,7 +1702,9 @@ class AssemblerRISCV(OpAssembler):
assert XLEN == 8 and FLEN == 8
self.mc.FMV_X_D(loc.value, prev_loc.value)
elif loc.is_stack():
- self.mc.store_float(prev_loc.value, r.jfp.value, loc.value)
+ self.mc.store_float_to_base_plus_offset(prev_loc.value,
+ r.jfp.value, loc.value,
+ tmp=r.x31.value)
else:
assert 0, 'unsupported case'
@@ -1701,7 +1713,8 @@ class AssemblerRISCV(OpAssembler):
self.mc.load_float_imm(loc.value, prev_loc.value)
elif loc.is_stack():
self.mc.load_float_imm(r.f31.value, prev_loc.value)
- self.mc.store_float(r.f31.value, r.jfp.value, loc.value)
+ self.mc.store_float_to_base_plus_offset(r.f31.value, r.jfp.value,
+ loc.value, tmp=r.x31.value)
else:
assert 0, 'unsupported case'
@@ -1713,7 +1726,8 @@ class AssemblerRISCV(OpAssembler):
elif loc.is_stack():
# Move a value from JITFRAME stack to raw stack.
scratch_reg = r.x31
- self.mc.load_int(scratch_reg.value, r.jfp.value, loc.value)
+ self.mc.load_int_from_base_plus_offset(scratch_reg.value,
+ r.jfp.value, loc.value)
self.mc.store_int(scratch_reg.value, r.sp.value, sp_offset)
elif loc.is_fp_reg():
self.mc.store_float(loc.value, r.sp.value, sp_offset)
diff --git a/rpython/jit/backend/riscv/codebuilder.py b/rpython/jit/backend/riscv/codebuilder.py
index 8e05b9640f..c5654e2a14 100644
--- a/rpython/jit/backend/riscv/codebuilder.py
+++ b/rpython/jit/backend/riscv/codebuilder.py
@@ -172,6 +172,26 @@ class AbstractRISCVBuilder(object):
def store_float(self, rs2, rs1, imm):
self.FSD(rs2, rs1, imm)
+ # Load an FLEN-bit float from rs1+imm (imm can be a large constant)
+ def load_float_from_base_plus_offset(self, rd, rs1, imm, tmp):
+ assert tmp != rs1
+ if check_imm_arg(imm):
+ self.load_float(rd, rs1, imm)
+ else:
+ self.load_int_imm(tmp, imm)
+ self.ADD(tmp, tmp, rs1)
+ self.load_float(rd, tmp, 0)
+
+ # Store an FLEN-bit float to rs1+imm (imm can be a large constant)
+ def store_float_to_base_plus_offset(self, rs2, rs1, imm, tmp):
+ assert tmp != rs1
+ if check_imm_arg(imm):
+ self.store_float(rs2, rs1, imm)
+ else:
+ self.load_int_imm(tmp, imm)
+ self.ADD(tmp, tmp, rs1)
+ self.store_float(rs2, tmp, 0)
+
# Load a rffi.INT from imm(rs1)
def load_rffi_int(self, rd, rs1, imm):
# Note: On RV64 (LP64), rffi.INT is 32-bit signed integer.