mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-09 22:48:57 +02:00
* tx86addnode.second_addfloat: use single and double-precision memory locations without loading them on FPU stack if possible.
git-svn-id: trunk@27558 -
This commit is contained in:
parent
0ef858a6ca
commit
3e20a136f3
@ -37,6 +37,7 @@ unit nx86add;
|
||||
function getresflags(unsigned : boolean) : tresflags;
|
||||
procedure left_must_be_reg(opdef: tdef; opsize:TCGSize;noswap:boolean);
|
||||
procedure force_left_and_right_fpureg;
|
||||
procedure prepare_x87_locations(out refnode: tnode);
|
||||
procedure emit_op_right_left(op:TAsmOp;opsize:TCgSize);
|
||||
procedure emit_generic_code(op:TAsmOp;opsize:TCgSize;unsigned,extra_not,mboverflow:boolean);
|
||||
|
||||
@ -258,6 +259,55 @@ unit nx86add;
|
||||
end;
|
||||
|
||||
|
||||
{ Makes sides suitable for executing an x87 instruction:
|
||||
if either side is OS_F32/OS_F64-sized LOC_REFERENCE, it is returned in 'refnode'
|
||||
everything else is loaded to FPU stack. }
|
||||
procedure tx86addnode.prepare_x87_locations(out refnode: tnode);
|
||||
begin
|
||||
refnode:=nil;
|
||||
case ord(left.location.loc=LOC_FPUREGISTER)+ord(right.location.loc=LOC_FPUREGISTER) of
|
||||
0:
|
||||
begin
|
||||
hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,false);
|
||||
if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
|
||||
InternalError(2013090803);
|
||||
if (left.location.size in [OS_F32,OS_F64]) then
|
||||
begin
|
||||
refnode:=left;
|
||||
toggleflag(nf_swapped);
|
||||
end
|
||||
else
|
||||
hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,false);
|
||||
end;
|
||||
1:
|
||||
begin { if left is on the stack then swap. }
|
||||
if (left.location.loc=LOC_FPUREGISTER) then
|
||||
refnode:=right
|
||||
else
|
||||
refnode:=left;
|
||||
if not(refnode.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
|
||||
InternalError(2013090801);
|
||||
if not (refnode.location.size in [OS_F32,OS_F64]) then
|
||||
begin
|
||||
hlcg.location_force_fpureg(current_asmdata.CurrAsmList,refnode.location,refnode.resultdef,false);
|
||||
if (refnode=right) then
|
||||
toggleflag(nf_swapped);
|
||||
refnode:=nil;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (refnode=left) then
|
||||
toggleflag(nf_swapped);
|
||||
end;
|
||||
end;
|
||||
2: { fpu operands are always in the wrong order on the stack }
|
||||
toggleflag(nf_swapped);
|
||||
else
|
||||
InternalError(2013090802);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure tx86addnode.emit_op_right_left(op:TAsmOp;opsize:TCgsize);
|
||||
{$ifdef x86_64}
|
||||
var
|
||||
@ -1096,8 +1146,17 @@ unit nx86add;
|
||||
|
||||
|
||||
procedure tx86addnode.second_addfloat;
|
||||
const
|
||||
ops_add: array[boolean] of TAsmOp = (A_FADDP,A_FADD);
|
||||
ops_mul: array[boolean] of TAsmOp = (A_FMULP,A_FMUL);
|
||||
ops_sub: array[boolean] of TAsmOp = (A_FSUBP,A_FSUB);
|
||||
ops_rsub: array[boolean] of TAsmOp = (A_FSUBRP,A_FSUBR);
|
||||
ops_div: array[boolean] of TAsmOp = (A_FDIVP,A_FDIV);
|
||||
ops_rdiv: array[boolean] of TAsmOp = (A_FDIVRP,A_FDIVR);
|
||||
var
|
||||
op : TAsmOp;
|
||||
refnode : tnode;
|
||||
hasref : boolean;
|
||||
begin
|
||||
if use_vectorfpu(resultdef) then
|
||||
begin
|
||||
@ -1109,34 +1168,36 @@ unit nx86add;
|
||||
end;
|
||||
|
||||
pass_left_right;
|
||||
prepare_x87_locations(refnode);
|
||||
hasref:=assigned(refnode);
|
||||
|
||||
case nodetype of
|
||||
addn :
|
||||
op:=A_FADDP;
|
||||
op:=ops_add[hasref];
|
||||
muln :
|
||||
op:=A_FMULP;
|
||||
op:=ops_mul[hasref];
|
||||
subn :
|
||||
op:=A_FSUBP;
|
||||
if (nf_swapped in flags) then
|
||||
op:=ops_rsub[hasref]
|
||||
else
|
||||
op:=ops_sub[hasref];
|
||||
slashn :
|
||||
op:=A_FDIVP;
|
||||
if (nf_swapped in flags) then
|
||||
op:=ops_rdiv[hasref]
|
||||
else
|
||||
op:=ops_div[hasref];
|
||||
else
|
||||
internalerror(2003042214);
|
||||
end;
|
||||
|
||||
force_left_and_right_fpureg;
|
||||
|
||||
{ if we swaped the tree nodes, then use the reverse operator }
|
||||
if nf_swapped in flags then
|
||||
if hasref then
|
||||
emit_ref(op,tcgsize2opsize[refnode.location.size],refnode.location.reference)
|
||||
else
|
||||
begin
|
||||
if (nodetype=slashn) then
|
||||
op:=A_FDIVRP
|
||||
else if (nodetype=subn) then
|
||||
op:=A_FSUBRP;
|
||||
emit_reg_reg(op,S_NO,NR_ST,NR_ST1);
|
||||
tcgx86(cg).dec_fpu_stack;
|
||||
end;
|
||||
|
||||
emit_reg_reg(op,S_NO,NR_ST,NR_ST1);
|
||||
tcgx86(cg).dec_fpu_stack;
|
||||
|
||||
location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
|
||||
location.register:=NR_ST;
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user