summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlaksen <laksen@3ad0048d-3df7-0310-abae-a5850022a9f2>2016-10-24 23:14:54 +0000
committerlaksen <laksen@3ad0048d-3df7-0310-abae-a5850022a9f2>2016-10-24 23:14:54 +0000
commit3b8ccd7dc6cdb55e234e10fe50a26cdd6d6a099d (patch)
tree69f48d285b0ea7dd818cef340c1cf3145b92e30e
parent086908f19e02c55fa99788b8f1dcc0174e0be1f6 (diff)
downloadfpc-3b8ccd7dc6cdb55e234e10fe50a26cdd6d6a099d.tar.gz
Fix emulated floating point double negation on 64bit architectures.
git-svn-id: http://svn.freepascal.org/svn/fpc/branches/laksen@34765 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--riscv/trunk/compiler/ncgmat.pas7
-rw-r--r--riscv/trunk/compiler/riscv/cgrv.pas2
-rw-r--r--riscv/trunk/compiler/riscv64/nrv64cnv.pas36
3 files changed, 28 insertions, 17 deletions
diff --git a/riscv/trunk/compiler/ncgmat.pas b/riscv/trunk/compiler/ncgmat.pas
index dc4bea1cc9..f7d3d87f43 100644
--- a/riscv/trunk/compiler/ncgmat.pas
+++ b/riscv/trunk/compiler/ncgmat.pas
@@ -232,11 +232,16 @@ implementation
secondpass(left);
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
location:=left.location;
- case location.size of
+ case location.size of
OS_32:
cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_XOR,OS_32,tcgint($80000000),location.register);
+{$ifdef cpu64bitalu}
+ OS_64:
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_XOR,OS_64,tcgint($8000000000000000),location.register);
+{$else cpu64bitalu}
OS_64:
cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_XOR,OS_32,tcgint($80000000),location.registerhi);
+{$endif cpu64bitalu}
else
internalerror(2014033101);
end;
diff --git a/riscv/trunk/compiler/riscv/cgrv.pas b/riscv/trunk/compiler/riscv/cgrv.pas
index 9ba638bf93..7e1d27efcb 100644
--- a/riscv/trunk/compiler/riscv/cgrv.pas
+++ b/riscv/trunk/compiler/riscv/cgrv.pas
@@ -192,7 +192,7 @@ unit cgrv;
list.concat(taicpu.op_reg_reg_const(TOpCG2AsmConstOp[op],dst,src,a))
else
begin
- tmpreg:=getintregister(list,OS_INT);
+ tmpreg:=getintregister(list,size);
a_load_const_reg(list,size,a,tmpreg);
a_op_reg_reg_reg(list,op,size,tmpreg,src,dst);
end;
diff --git a/riscv/trunk/compiler/riscv64/nrv64cnv.pas b/riscv/trunk/compiler/riscv64/nrv64cnv.pas
index 9a7c80c6f1..531b6d49f1 100644
--- a/riscv/trunk/compiler/riscv64/nrv64cnv.pas
+++ b/riscv/trunk/compiler/riscv64/nrv64cnv.pas
@@ -70,22 +70,28 @@ unit nrv64cnv;
*****************************************************************************}
function trv64typeconvnode.first_int_to_real: tnode;
- begin
- if (is_currency(left.resultdef)) then begin
- // hack to avoid double division by 10000, as it's
- // already done by typecheckpass.resultdef_int_to_real
- left.resultdef := s64inttype;
- end else begin
- // everything that is less than 64 bits is converted to a 64 bit signed
- // integer - because the int_to_real conversion is faster for 64 bit
- // signed ints compared to 64 bit unsigned ints.
- if (not (torddef(left.resultdef).ordtype in [s64bit, u64bit, scurrency])) then begin
- inserttypeconv(left, s64inttype);
+ begin
+ if (cs_fp_emulation in current_settings.moduleswitches) then
+ result:=inherited first_int_to_real
+ { converting a 64bit integer to a float requires a helper }
+ else
+ begin
+ if (is_currency(left.resultdef)) then begin
+ // hack to avoid double division by 10000, as it's
+ // already done by typecheckpass.resultdef_int_to_real
+ left.resultdef := s64inttype;
+ end else begin
+ // everything that is less than 64 bits is converted to a 64 bit signed
+ // integer - because the int_to_real conversion is faster for 64 bit
+ // signed ints compared to 64 bit unsigned ints.
+ if (not (torddef(left.resultdef).ordtype in [s64bit, u64bit, scurrency])) then begin
+ inserttypeconv(left, s64inttype);
+ end;
+ end;
+ firstpass(left);
+ result := nil;
+ expectloc := LOC_FPUREGISTER;
end;
- end;
- firstpass(left);
- result := nil;
- expectloc := LOC_FPUREGISTER;
end;
{*****************************************************************************