diff --git a/compiler/i386/n386add.pas b/compiler/i386/n386add.pas index c2cb8c4ac4..7aaeec3f02 100644 --- a/compiler/i386/n386add.pas +++ b/compiler/i386/n386add.pas @@ -686,6 +686,8 @@ interface label do_normal; var + unusedregisters : tregisterset; + usablecount : byte; hregister,hregister2 : tregister; noswap,popeax,popedx, pushed,mboverflow,cmpop : boolean; @@ -1657,15 +1659,18 @@ interface if nodetype=muln then begin - { save lcoation, because we change it now } - set_location(hloc,location); - release_qword_loc(location); - release_qword_loc(right.location); - location.registerlow:=getexplicitregister32(R_EAX); - location.registerhigh:=getexplicitregister32(R_EDX); - pushusedregisters(pushedreg,$ff - and not($80 shr byte(location.registerlow)) - and not($80 shr byte(location.registerhigh))); + regstopush := $ff; + remove_non_regvars_from_loc(location,regstopush); + remove_non_regvars_from_loc(right.location,regstopush); + + { ugly hack because in *this* case, the pushed register } + { must not be allocated later on (JM) } + unusedregisters:=unused; + usablecount:=usablereg32; + pushusedregisters(pushedreg,regstopush); + unused:=unusedregisters; + usablereg32:=usablecount; + if cs_check_overflow in aktlocalswitches then push_int(1) else @@ -1673,19 +1678,35 @@ interface { the left operand is in hloc, because the location of left is location but location is already destroyed + + not anymore... I had to change this because the + regalloc info was completely wrong otherwise (JM) } - emit_pushq_loc(hloc); - clear_location(hloc); + emit_pushq_loc(location); + release_qword_loc(location); + clear_location(location); emit_pushq_loc(right.location); + release_qword_loc(right.location); saveregvars($ff); if torddef(resulttype.def).typ=u64bit then emitcall('FPC_MUL_QWORD') else emitcall('FPC_MUL_INT64'); + { make sure we don't overwrite any results (JM) } + if R_EDX in unused then + begin + location.registerhigh:=getexplicitregister32(R_EDX); + location.registerlow:=getexplicitregister32(R_EAX); + end + else + begin + location.registerlow:=getexplicitregister32(R_EAX); + location.registerhigh:=getexplicitregister32(R_EDX); + end; + location.loc := LOC_REGISTER; emit_reg_reg(A_MOV,S_L,R_EAX,location.registerlow); emit_reg_reg(A_MOV,S_L,R_EDX,location.registerhigh); popusedregisters(pushedreg); - location.loc:=LOC_REGISTER; end else begin @@ -2293,7 +2314,11 @@ begin end. { $Log$ - Revision 1.17 2001-08-26 13:36:55 florian + Revision 1.18 2001-08-29 12:03:23 jonas + * fixed wrong regalloc info around FPC_MUL/DIV/MOD_INT64/QWORD calls + * fixed partial result overwriting with the above calls too + + Revision 1.17 2001/08/26 13:36:55 florian * some cg reorganisation * some PPC updates diff --git a/compiler/i386/n386mat.pas b/compiler/i386/n386mat.pas index 339bc0824c..33377067b1 100644 --- a/compiler/i386/n386mat.pas +++ b/compiler/i386/n386mat.pas @@ -64,6 +64,8 @@ implementation procedure ti386moddivnode.pass_2; var + unusedregisters : tregisterset; + usablecount, regstopush : byte; hreg1 : tregister; hreg2 : tregister; shrdiv, andmod, pushed,popeax,popedx : boolean; @@ -86,23 +88,23 @@ implementation if is_64bitint(resulttype.def) then begin - { save lcoation, because we change it now } - set_location(hloc,location); + regstopush := $ff; + remove_non_regvars_from_loc(location,regstopush); + remove_non_regvars_from_loc(right.location,regstopush); + + { ugly hack because in *this* case, the pushed register } + { must not be allocated later on (JM) } + unusedregisters:=unused; + usablecount:=usablereg32; + pushusedregisters(pushedreg,regstopush); + unused:=unusedregisters; + usablereg32:=usablecount; + + emit_pushq_loc(location); release_qword_loc(location); - release_qword_loc(right.location); - location.registerlow:=getexplicitregister32(R_EAX); - location.registerhigh:=getexplicitregister32(R_EDX); - pushusedregisters(pushedreg,$ff - and not($80 shr byte(location.registerlow)) - and not($80 shr byte(location.registerhigh))); - { the left operand is in hloc, because the - location of left is location but location - is already destroyed - } - emit_pushq_loc(hloc); - clear_location(hloc); + clear_location(location); emit_pushq_loc(right.location); - + release_qword_loc(right.location); if torddef(resulttype.def).typ=u64bit then typename:='QWORD' else @@ -114,10 +116,22 @@ implementation saveregvars($ff); emitcall('FPC_'+opname+typename); + { make sure we don't overwrite any results (JM) } + if R_EDX in unused then + begin + location.registerhigh:=getexplicitregister32(R_EDX); + location.registerlow:=getexplicitregister32(R_EAX); + end + else + begin + location.registerlow:=getexplicitregister32(R_EAX); + location.registerhigh:=getexplicitregister32(R_EDX); + end; + location.loc:=LOC_REGISTER; emit_reg_reg(A_MOV,S_L,R_EAX,location.registerlow); emit_reg_reg(A_MOV,S_L,R_EDX,location.registerhigh); + popusedregisters(pushedreg); - location.loc:=LOC_REGISTER; end else begin @@ -476,7 +490,9 @@ implementation begin popecx:=true; emit_reg(A_PUSH,S_L,R_ECX); - end; + end + else + getexplicitregister32(R_ECX); emit_reg_reg(A_MOV,S_L,hregister2,R_ECX); end; @@ -1042,7 +1058,11 @@ begin end. { $Log$ - Revision 1.14 2001-08-26 13:37:00 florian + Revision 1.15 2001-08-29 12:03:23 jonas + * fixed wrong regalloc info around FPC_MUL/DIV/MOD_INT64/QWORD calls + * fixed partial result overwriting with the above calls too + + Revision 1.14 2001/08/26 13:37:00 florian * some cg reorganisation * some PPC updates