Add rounding mode operands.

Add support for trunc and round methods.

git-svn-id: branches/laksen/riscv_new@39698 -
This commit is contained in:
Jeppe Johansen 2018-09-01 19:48:44 +00:00
parent 2af0ca8546
commit 29ea4ed07d
5 changed files with 132 additions and 1 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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 =

View File

@ -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
*****************************************************************************}