diff options
author | jonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2012-06-21 17:05:38 +0000 |
---|---|---|
committer | jonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2012-06-21 17:05:38 +0000 |
commit | 23147ccb3831b380d59103110b1fa5d2dd78083d (patch) | |
tree | 3184075f742375a86654baa4ffc50ea08f069851 /compiler/hlcgobj.pas | |
parent | 9dbfa5414af9a2728d76085b6bd710453f11362b (diff) | |
download | fpc-23147ccb3831b380d59103110b1fa5d2dd78083d.tar.gz |
* properly handle loading a value from a larger to a smaller subsetreg
if the source value comes from a bit position > sizeof(smaller subsetreg)
(fixes internalerror 68991 when compiling fpcompactimg.inc for ppc64)
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@21675 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'compiler/hlcgobj.pas')
-rw-r--r-- | compiler/hlcgobj.pas | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/compiler/hlcgobj.pas b/compiler/hlcgobj.pas index 5883bb264d..717986c83c 100644 --- a/compiler/hlcgobj.pas +++ b/compiler/hlcgobj.pas @@ -1039,7 +1039,7 @@ implementation var fromsubsetregdef, tosubsetregdef: torddef; - tmpreg: tregister; + tmpreg, tmpreg2: tregister; bitmask: aword; stopbit: byte; begin @@ -1047,12 +1047,22 @@ implementation begin fromsubsetregdef:=tcgsize2orddef(fromsreg.subsetregsize); tosubsetregdef:=tcgsize2orddef(tosreg.subsetregsize); - tmpreg:=getintregister(list,tosubsetregdef); - a_load_reg_reg(list,fromsubsetregdef,tosubsetregdef,fromsreg.subsetreg,tmpreg); if (fromsreg.startbit<=tosreg.startbit) then - a_op_const_reg(list,OP_SHL,tosubsetregdef,tosreg.startbit-fromsreg.startbit,tmpreg) + begin + { tosreg may be larger -> use its size to perform the shift } + tmpreg:=getintregister(list,tosubsetregdef); + a_load_reg_reg(list,fromsubsetregdef,tosubsetregdef,fromsreg.subsetreg,tmpreg); + a_op_const_reg(list,OP_SHL,tosubsetregdef,tosreg.startbit-fromsreg.startbit,tmpreg) + end else - a_op_const_reg(list,OP_SHR,tosubsetregdef,fromsreg.startbit-tosreg.startbit,tmpreg); + begin + { fromsreg may be larger -> use its size to perform the shift } + tmpreg:=getintregister(list,fromsubsetregdef); + a_op_const_reg_reg(list,OP_SHR,fromsubsetregdef,fromsreg.startbit-tosreg.startbit,fromsreg.subsetreg,tmpreg); + tmpreg2:=getintregister(list,tosubsetregdef); + a_load_reg_reg(list,fromsubsetregdef,tosubsetregdef,tmpreg,tmpreg2); + tmpreg:=tmpreg2; + end; stopbit:=tosreg.startbit + tosreg.bitlen; // on x86(64), 1 shl 32(64) = 1 instead of 0 if (stopbit<>AIntBits) then |