diff --git a/.gitattributes b/.gitattributes index 011a4f6e48..05348ac46e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -6265,6 +6265,7 @@ tests/tbs/tb0531.pp svneol=native#text/plain tests/tbs/tb0532.pp svneol=native#text/x-pascal tests/tbs/tb0533.pp svneol=native#text/plain tests/tbs/tb0534.pp svneol=native#text/plain +tests/tbs/tb0535.pp svneol=native#text/plain tests/tbs/ub0060.pp svneol=native#text/plain tests/tbs/ub0069.pp svneol=native#text/plain tests/tbs/ub0119.pp svneol=native#text/plain diff --git a/compiler/x86/nx86add.pas b/compiler/x86/nx86add.pas index 2ab25af7e8..6628a7500a 100644 --- a/compiler/x86/nx86add.pas +++ b/compiler/x86/nx86add.pas @@ -35,7 +35,7 @@ unit nx86add; protected function getresflags(unsigned : boolean) : tresflags; procedure left_must_be_reg(opsize:TCGSize;noswap:boolean); - procedure left_and_right_must_be_fpureg; + procedure check_left_and_right_fpureg(force_fpureg: boolean); procedure emit_op_right_left(op:TAsmOp;opsize:TCgSize); procedure emit_generic_code(op:TAsmOp;opsize:TCgSize;unsigned,extra_not,mboverflow:boolean); @@ -212,25 +212,31 @@ unit nx86add; end; - procedure tx86addnode.left_and_right_must_be_fpureg; + procedure tx86addnode.check_left_and_right_fpureg(force_fpureg: boolean); begin if (right.location.loc<>LOC_FPUREGISTER) then begin - location_force_fpureg(current_asmdata.CurrAsmList,right.location,false); - if (left.location.loc<>LOC_FPUREGISTER) then - location_force_fpureg(current_asmdata.CurrAsmList,left.location,false) - else - { left was on the stack => swap } - toggleflag(nf_swapped); + if (force_fpureg) then + begin + location_force_fpureg(current_asmdata.CurrAsmList,right.location,false); + if (left.location.loc<>LOC_FPUREGISTER) then + location_force_fpureg(current_asmdata.CurrAsmList,left.location,false) + else + { left was on the stack => swap } + toggleflag(nf_swapped); + end end { the nominator in st0 } else if (left.location.loc<>LOC_FPUREGISTER) then - location_force_fpureg(current_asmdata.CurrAsmList,left.location,false) + begin + if (force_fpureg) then + location_force_fpureg(current_asmdata.CurrAsmList,left.location,false) + end else - begin - { fpu operands are always in the wrong order on the stack } - toggleflag(nf_swapped); - end; + begin + { fpu operands are always in the wrong order on the stack } + toggleflag(nf_swapped); + end; end; @@ -700,8 +706,16 @@ unit nx86add; op : topcg; begin pass_left_right; + check_left_and_right_fpureg(false); + if (nf_swapped in flags) then - swapleftright; + { can't use swapleftright if both are on the fpu stack, since then } + { both are "R_ST" -> nothing would change -> manually switch } + if (left.location.loc = LOC_FPUREGISTER) and + (right.location.loc = LOC_FPUREGISTER) then + emit_none(A_FXCH,S_NO) + else + swapleftright; case nodetype of addn : @@ -885,7 +899,7 @@ unit nx86add; internalerror(2003042214); end; - left_and_right_must_be_fpureg; + check_left_and_right_fpureg(true); { if we swaped the tree nodes, then use the reverse operator } if nf_swapped in flags then @@ -915,7 +929,7 @@ unit nx86add; end; pass_left_right; - left_and_right_must_be_fpureg; + check_left_and_right_fpureg(true); {$ifndef x86_64} if current_settings.cputype 2 then + halt(1); +end.