mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-14 08:46:08 +02:00
Add rounding mode operands.
Add support for trunc and round methods. git-svn-id: branches/laksen/riscv_new@39698 -
This commit is contained in:
parent
2af0ca8546
commit
29ea4ed07d
@ -264,6 +264,7 @@ interface
|
||||
{$endif llvm}
|
||||
{$if defined(riscv32) or defined(riscv64)}
|
||||
,top_fenceflags
|
||||
,top_roundingmode
|
||||
{$endif defined(riscv32) or defined(riscv64)}
|
||||
);
|
||||
|
||||
@ -468,6 +469,7 @@ interface
|
||||
{$endif llvm}
|
||||
{$if defined(riscv32) or defined(riscv64)}
|
||||
top_fenceflags : (fenceflags : TFenceFlags);
|
||||
top_roundingmode : (roundingmode : TRoundingMode);
|
||||
{$endif defined(riscv32) or defined(riscv64)}
|
||||
end;
|
||||
poper=^toper;
|
||||
|
@ -38,6 +38,9 @@ uses
|
||||
|
||||
|
||||
type
|
||||
|
||||
{ taicpu }
|
||||
|
||||
taicpu = class(tai_cpu_abstract_sym)
|
||||
memoryordering: TMemoryOrdering;
|
||||
constructor op_none(op : tasmop);
|
||||
@ -54,6 +57,7 @@ uses
|
||||
|
||||
constructor op_reg_reg_const_const(op: tasmop; _op1, _op2: tregister; _op3, _op4: aint);
|
||||
|
||||
constructor op_reg_reg_roundingmode(op : tasmop;_op1,_op2 : tregister; _op3: TRoundingMode);
|
||||
constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
|
||||
constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
|
||||
constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: aint);
|
||||
@ -82,6 +86,7 @@ uses
|
||||
constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : aint);
|
||||
constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:aint;const _op2 : treference);
|
||||
|
||||
procedure loadroundingmode(opidx:aint;_roundmode:TRoundingMode);
|
||||
procedure loadfenceflags(opidx:aint;_flags:TFenceFlags);
|
||||
procedure loadbool(opidx:aint;_b:boolean);
|
||||
|
||||
@ -201,6 +206,16 @@ uses cutils, cclasses;
|
||||
end;
|
||||
|
||||
|
||||
constructor taicpu.op_reg_reg_roundingmode(op: tasmop; _op1, _op2: tregister; _op3: TRoundingMode);
|
||||
begin
|
||||
inherited create(op);
|
||||
ops:=3;
|
||||
loadreg(0,_op1);
|
||||
loadreg(1,_op2);
|
||||
loadroundingmode(2,_op3);
|
||||
end;
|
||||
|
||||
|
||||
constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
|
||||
begin
|
||||
inherited create(op);
|
||||
@ -388,6 +403,19 @@ uses cutils, cclasses;
|
||||
end;
|
||||
|
||||
|
||||
procedure taicpu.loadroundingmode(opidx: aint; _roundmode: TRoundingMode);
|
||||
begin
|
||||
allocate_oper(opidx+1);
|
||||
with oper[opidx]^ do
|
||||
begin
|
||||
if typ<>top_roundingmode then
|
||||
clearop(opidx);
|
||||
roundingmode:=_roundmode;
|
||||
typ:=top_roundingmode;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure taicpu.loadfenceflags(opidx: aint; _flags: TFenceFlags);
|
||||
begin
|
||||
allocate_oper(opidx+1);
|
||||
|
@ -174,7 +174,9 @@ unit agrvgas;
|
||||
if ffO in o.fenceflags then getopstr:=getopstr+'o';
|
||||
if ffR in o.fenceflags then getopstr:=getopstr+'r';
|
||||
if ffW in o.fenceflags then getopstr:=getopstr+'w';
|
||||
end
|
||||
end;
|
||||
top_roundingmode:
|
||||
getopstr:=roundingmode2str[o.roundingmode];
|
||||
else
|
||||
internalerror(2002070604);
|
||||
end;
|
||||
|
@ -30,6 +30,9 @@ interface
|
||||
node,ninl,ncginl;
|
||||
|
||||
type
|
||||
|
||||
{ trvinlinenode }
|
||||
|
||||
trvinlinenode = class(tcginlinenode)
|
||||
{ first pass override
|
||||
so that the code generator will actually generate
|
||||
@ -38,12 +41,16 @@ interface
|
||||
function first_sqrt_real: tnode; override;
|
||||
function first_abs_real: tnode; override;
|
||||
function first_sqr_real: tnode; override;
|
||||
function first_round_real: tnode; override;
|
||||
function first_trunc_real: tnode; override;
|
||||
|
||||
function first_fma: tnode; override;
|
||||
|
||||
procedure second_sqrt_real; override;
|
||||
procedure second_abs_real; override;
|
||||
procedure second_sqr_real; override;
|
||||
procedure second_round_real; override;
|
||||
procedure second_trunc_real; override;
|
||||
|
||||
procedure second_fma; override;
|
||||
protected
|
||||
@ -102,6 +109,31 @@ implementation
|
||||
result:=inherited first_sqr_real;
|
||||
end;
|
||||
|
||||
|
||||
function trvinlinenode.first_round_real: tnode;
|
||||
begin
|
||||
if (current_settings.fputype >= fpu_fd) then
|
||||
begin
|
||||
expectloc:=LOC_FPUREGISTER;
|
||||
first_round_real := nil;
|
||||
end
|
||||
else
|
||||
result:=inherited first_round_real;
|
||||
end;
|
||||
|
||||
|
||||
function trvinlinenode.first_trunc_real: tnode;
|
||||
begin
|
||||
if (current_settings.fputype >= fpu_fd) then
|
||||
begin
|
||||
expectloc:=LOC_FPUREGISTER;
|
||||
first_trunc_real := nil;
|
||||
end
|
||||
else
|
||||
result:=inherited first_trunc_real;
|
||||
end;
|
||||
|
||||
|
||||
function trvinlinenode.first_fma: tnode;
|
||||
begin
|
||||
Result:=nil;
|
||||
@ -171,6 +203,62 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure trvinlinenode.second_round_real;
|
||||
var
|
||||
op: TAsmOp;
|
||||
begin
|
||||
secondpass(left);
|
||||
hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
|
||||
location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
|
||||
location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
|
||||
{ convert to signed integer rounding towards zero (there's no "round to
|
||||
integer using current rounding mode") }
|
||||
|
||||
{$ifdef RISCV32}
|
||||
if (left.location.size = OS_F32) then
|
||||
op := A_FCVT_W_S
|
||||
else
|
||||
op := A_FCVT_W_D;
|
||||
{$else}
|
||||
if (left.location.size = OS_F32) then
|
||||
op := A_FCVT_L_S
|
||||
else
|
||||
op := A_FCVT_L_D;
|
||||
{$endif}
|
||||
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,location.register,left.location.register));
|
||||
cg.g_check_for_fpu_exception(current_asmdata.CurrAsmList);
|
||||
end;
|
||||
|
||||
|
||||
procedure trvinlinenode.second_trunc_real;
|
||||
var
|
||||
op: TAsmOp;
|
||||
begin
|
||||
secondpass(left);
|
||||
hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
|
||||
location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
|
||||
location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
|
||||
{ convert to signed integer rounding towards zero (there's no "round to
|
||||
integer using current rounding mode") }
|
||||
|
||||
{$ifdef RISCV32}
|
||||
if (left.location.size = OS_F32) then
|
||||
op := A_FCVT_W_S
|
||||
else
|
||||
op := A_FCVT_W_D;
|
||||
{$else}
|
||||
if (left.location.size = OS_F32) then
|
||||
op := A_FCVT_L_S
|
||||
else
|
||||
op := A_FCVT_L_D;
|
||||
{$endif}
|
||||
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_roundingmode(op,location.register,left.location.register,RM_RTZ));
|
||||
cg.g_check_for_fpu_exception(current_asmdata.CurrAsmList);
|
||||
end;
|
||||
|
||||
|
||||
procedure trvinlinenode.second_fma;
|
||||
const
|
||||
op : array[os_f32..os_f64,false..true,false..true] of TAsmOp =
|
||||
|
@ -170,6 +170,17 @@ type
|
||||
TFenceFlag = (ffI, ffO, ffR, ffW);
|
||||
TFenceFlags = set of TFenceFlag;
|
||||
|
||||
TRoundingMode = (RM_Default,
|
||||
RM_RNE,
|
||||
RM_RTZ,
|
||||
RM_RDN,
|
||||
RM_RUP,
|
||||
RM_RMM);
|
||||
|
||||
const
|
||||
roundingmode2str : array[TRoundingMode] of string[3] = ('',
|
||||
'rne','rtz','rdn','rup','rmm');
|
||||
|
||||
{*****************************************************************************
|
||||
Conditions
|
||||
*****************************************************************************}
|
||||
|
Loading…
Reference in New Issue
Block a user