From 2aa3270ca086421f4b521c48ba59661cec87d571 Mon Sep 17 00:00:00 2001 From: Pierre Muller Date: Sun, 6 Nov 2022 22:14:38 +0000 Subject: [PATCH] Handle unaligned references in 64-bit a_load_ref_reg and a_load_reg_ref methods (cherry picked from commit c96bb0f4164d45afe3a0cc8d4e306f0b5c14dbeb) --- compiler/mips/cgcpu.pas | 88 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/compiler/mips/cgcpu.pas b/compiler/mips/cgcpu.pas index 416c6c283f..b0d3a85e9e 100644 --- a/compiler/mips/cgcpu.pas +++ b/compiler/mips/cgcpu.pas @@ -1699,6 +1699,7 @@ procedure TCg64MPSel.a_load64_reg_ref(list: tasmlist; reg: tregister64; const re var tmpref: treference; tmpreg: tregister; + incr: shortint; begin if target_info.endian = endian_big then begin @@ -1708,9 +1709,46 @@ begin end; tmpref := ref; tcgmips(cg).make_simple_ref(list,tmpref); - list.concat(taicpu.op_reg_ref(A_SW,reg.reglo,tmpref)); - Inc(tmpref.offset, 4); - list.concat(taicpu.op_reg_ref(A_SW,reg.reghi,tmpref)); + if (ref.alignment <4) then + begin + if target_info.endian = endian_big then + begin + inc(tmpref.offset,3); + incr:=-1; + end + else + incr:=1; + list.concat(taicpu.op_reg_ref(A_SB,reg.reglo,tmpref)); + Inc(tmpref.offset,incr); + list.concat(taicpu.op_reg_reg_const(A_SRL,reg.reglo,reg.reglo,8)); + list.concat(taicpu.op_reg_ref(A_SB,reg.reglo,tmpref)); + Inc(tmpref.offset,incr); + list.concat(taicpu.op_reg_reg_const(A_SRL,reg.reglo,reg.reglo,8)); + list.concat(taicpu.op_reg_ref(A_SB,reg.reglo,tmpref)); + Inc(tmpref.offset,incr); + list.concat(taicpu.op_reg_reg_const(A_SRL,reg.reglo,reg.reglo,8)); + list.concat(taicpu.op_reg_ref(A_SB,reg.reglo,tmpref)); + Inc(tmpref.offset,incr); + if target_info.endian = endian_big then + inc(tmpref.offset,7); + list.concat(taicpu.op_reg_ref(A_SB,reg.reghi,tmpref)); + Inc(tmpref.offset,incr); + list.concat(taicpu.op_reg_reg_const(A_SRL,reg.reghi,reg.reghi,8)); + list.concat(taicpu.op_reg_ref(A_SB,reg.reghi,tmpref)); + Inc(tmpref.offset,incr); + list.concat(taicpu.op_reg_reg_const(A_SRL,reg.reghi,reg.reghi,8)); + list.concat(taicpu.op_reg_ref(A_SB,reg.reghi,tmpref)); + Inc(tmpref.offset,incr); + list.concat(taicpu.op_reg_reg_const(A_SRL,reg.reghi,reg.reghi,8)); + list.concat(taicpu.op_reg_ref(A_SB,reg.reghi,tmpref)); + Inc(tmpref.offset,incr); + end + else + begin + list.concat(taicpu.op_reg_ref(A_SW,reg.reglo,tmpref)); + Inc(tmpref.offset, 4); + list.concat(taicpu.op_reg_ref(A_SW,reg.reghi,tmpref)); + end; end; @@ -1718,6 +1756,7 @@ procedure TCg64MPSel.a_load64_ref_reg(list: tasmlist; const ref: treference; reg var tmpref: treference; tmpreg: tregister; + incr: shortint; begin if target_info.endian = endian_big then begin @@ -1727,9 +1766,46 @@ begin end; tmpref := ref; tcgmips(cg).make_simple_ref(list,tmpref); - list.concat(taicpu.op_reg_ref(A_LW,reg.reglo,tmpref)); - Inc(tmpref.offset, 4); - list.concat(taicpu.op_reg_ref(A_LW,reg.reghi,tmpref)); + if (ref.alignment <4) then + begin + if target_info.endian = endian_big then + begin + inc(tmpref.offset,3); + incr:=-1; + end + else + incr:=1; + list.concat(taicpu.op_reg_ref(A_LBU,reg.reglo,tmpref)); + Inc(tmpref.offset,incr); + list.concat(taicpu.op_reg_reg_const(A_SLL,reg.reglo,reg.reglo,8)); + list.concat(taicpu.op_reg_ref(A_LBU,reg.reglo,tmpref)); + Inc(tmpref.offset,incr); + list.concat(taicpu.op_reg_reg_const(A_SLL,reg.reglo,reg.reglo,8)); + list.concat(taicpu.op_reg_ref(A_LBU,reg.reglo,tmpref)); + Inc(tmpref.offset,incr); + list.concat(taicpu.op_reg_reg_const(A_SLL,reg.reglo,reg.reglo,8)); + list.concat(taicpu.op_reg_ref(A_LBU,reg.reglo,tmpref)); + Inc(tmpref.offset,incr); + if target_info.endian = endian_big then + inc(tmpref.offset,7); + list.concat(taicpu.op_reg_ref(A_LBU,reg.reghi,tmpref)); + Inc(tmpref.offset,incr); + list.concat(taicpu.op_reg_reg_const(A_SLL,reg.reghi,reg.reghi,8)); + list.concat(taicpu.op_reg_ref(A_LBU,reg.reghi,tmpref)); + Inc(tmpref.offset,incr); + list.concat(taicpu.op_reg_reg_const(A_SLL,reg.reghi,reg.reghi,8)); + list.concat(taicpu.op_reg_ref(A_LBU,reg.reghi,tmpref)); + Inc(tmpref.offset,incr); + list.concat(taicpu.op_reg_reg_const(A_SLL,reg.reghi,reg.reghi,8)); + list.concat(taicpu.op_reg_ref(A_LBU,reg.reghi,tmpref)); + Inc(tmpref.offset,incr); + end + else + begin + list.concat(taicpu.op_reg_ref(A_LW,reg.reglo,tmpref)); + Inc(tmpref.offset, 4); + list.concat(taicpu.op_reg_ref(A_LW,reg.reghi,tmpref)); + end; end;