diff options
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 |