diff --git a/compiler/aggas.pas b/compiler/aggas.pas index b84f0d505d..4478bc3dc4 100644 --- a/compiler/aggas.pas +++ b/compiler/aggas.pas @@ -211,7 +211,7 @@ implementation { vtable for a class called Window: } { .section .data.rel.ro._ZTV6Window,"awG",@progbits,_ZTV6Window,comdat } { TODO: .data.ro not yet working} -{$if defined(arm) or defined(powerpc)} +{$if defined(arm) or defined(riscv64) or defined(powerpc)} '.rodata', {$else arm} '.data', diff --git a/compiler/riscv/cgrv.pas b/compiler/riscv/cgrv.pas index 0cbfd753c0..5a616925bf 100644 --- a/compiler/riscv/cgrv.pas +++ b/compiler/riscv/cgrv.pas @@ -198,19 +198,19 @@ unit cgrv; {$ifdef RISCV64} if (op=OP_SHL) and - (size in [OS_32,OS_S32]) then + (size=OS_S32) then begin list.concat(taicpu.op_reg_reg_const(A_SLLIW,dst,src,a)); maybeadjustresult(list,op,size,dst); end else if (op=OP_SHR) and - (size in [OS_32,OS_S32]) then + (size=OS_S32) then begin list.concat(taicpu.op_reg_reg_const(A_SRLIW,dst,src,a)); maybeadjustresult(list,op,size,dst); end else if (op=OP_SAR) and - (size in [OS_32,OS_S32]) then + (size=OS_S32) then begin list.concat(taicpu.op_reg_reg_const(A_SRAIW,dst,src,a)); maybeadjustresult(list,op,size,dst); @@ -251,19 +251,19 @@ unit cgrv; else {$ifdef RISCV64} if (op=OP_SHL) and - (size in [OS_32,OS_S32]) then + (size=OS_S32) then begin list.concat(taicpu.op_reg_reg_reg(A_SLLW,dst,src2,src1)); maybeadjustresult(list,op,size,dst); end else if (op=OP_SHR) and - (size in [OS_32,OS_S32]) then + (size=OS_S32) then begin list.concat(taicpu.op_reg_reg_reg(A_SRLW,dst,src2,src1)); maybeadjustresult(list,op,size,dst); end else if (op=OP_SAR) and - (size in [OS_32,OS_S32]) then + (size=OS_S32) then begin list.concat(taicpu.op_reg_reg_reg(A_SRAW,dst,src2,src1)); maybeadjustresult(list,op,size,dst); diff --git a/compiler/riscv64/cgcpu.pas b/compiler/riscv64/cgcpu.pas index 6f028d5448..554107ab91 100644 --- a/compiler/riscv64/cgcpu.pas +++ b/compiler/riscv64/cgcpu.pas @@ -95,8 +95,12 @@ implementation var ai: taicpu; begin + list.concat(tai_comment.Create(strpnew('Move '+tcgsize2str(fromsize)+'->'+tcgsize2str(tosize)))); + if (tcgsize2unsigned[tosize]=OS_64) and (fromsize=OS_S32) then list.Concat(taicpu.op_reg_reg_const(A_ADDIW,reg2,reg1,0)) + else if (tosize=OS_S32) and (tcgsize2unsigned[fromsize]=OS_64) then + list.Concat(taicpu.op_reg_reg_const(A_ADDIW,reg2,reg1,0)) else if (tcgsize2unsigned[tosize]=OS_64) and (fromsize=OS_8) then list.Concat(taicpu.op_reg_reg_const(A_ANDI,reg2,reg1,$FF)) else if (tcgsize2size[fromsize] > tcgsize2size[tosize]) or @@ -187,69 +191,15 @@ implementation l: TAsmLabel; tmpreg: tregister; ai: taicpu; - begin - signed:=tcgsize2unsigned[size]<>size; - - if setflags and - (op=OP_ADD) and - (src=dst) and - (not signed) then + begin + if setflags then begin tmpreg:=getintregister(list,size); - a_load_reg_reg(list,size,size,src,tmpreg); - src:=tmpreg; - end; - - a_op_const_reg_reg(list,op,size,a,src,dst); - - if setflags and - (op=OP_ADD) then - begin - current_asmdata.getjumplabel(l); - if signed then - begin - { - t0=a<0 - t1=resultsize; - if setflags and - (op=OP_ADD) and - (src2=dst) and - (not signed) then - begin - tmpreg:=getintregister(list,size); - a_load_reg_reg(list,size,size,src2,tmpreg); - src2:=tmpreg; - end; - - a_op_reg_reg_reg(list,op,size,src1,src2,dst); - - if setflags and - (op=OP_ADD) then - begin - current_asmdata.getjumplabel(l); - if signed then + if setflags then + case op of + OP_ADD: begin - { - t0=src1<0 - t1=resultt1 + } + tmpreg0:=getintregister(list,OS_INT); + tmpreg:=getintregister(list,OS_INT); + list.Concat(taicpu.op_reg_reg_reg(A_SLT,tmpreg0,src1,NR_X0)); + list.Concat(taicpu.op_reg_reg_reg(A_SLT,tmpreg,dst,src2)); + + ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,tmpreg,tmpreg0,l,0); + ai.condition:=C_EQ; + list.concat(ai); + end + else + begin + { + jump if sum>=x + } + if size in [OS_S32,OS_32] then + begin + tmpreg:=getintregister(list,OS_INT); + a_load_reg_reg(list,size,OS_64,dst,tmpreg); + dst:=tmpreg; + end; + + ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,dst,src2,l,0); + ai.condition:=C_GEU; + list.concat(ai); end; - tmpreg:=getintregister(list,OS_INT); - list.Concat(taicpu.op_reg_reg_reg(A_SLTU,tmpreg,dst,src2)); - ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,tmpreg,NR_X0,l,0); - ai.condition:=C_EQ; - list.concat(ai); + a_call_name(list,'FPC_OVERFLOW',false); + a_label(list,l); end; + OP_SUB: + begin + current_asmdata.getjumplabel(l); - a_call_name(list,'FPC_OVERFLOW',false); - a_label(list,l); - end; + list.Concat(taicpu.op_reg_reg_reg(A_SUB,dst,src2,src1)); + + if signed then + begin + tmpreg0:=getintregister(list,OS_INT); + tmpreg:=getintregister(list,OS_INT); + list.Concat(taicpu.op_reg_reg_reg(A_SLT,tmpreg0,NR_X0,src1)); + list.Concat(taicpu.op_reg_reg_reg(A_SLT,tmpreg,dst,src2)); + + ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,tmpreg,tmpreg0,l,0); + ai.condition:=C_EQ; + list.concat(ai); + end + else + begin + { no overflow if result<=src2 } + if size in [OS_S32,OS_32] then + begin + tmpreg:=getintregister(list,OS_INT); + a_load_reg_reg(list,size,OS_64,dst,tmpreg); + dst:=tmpreg; + end; + + ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,src2,dst,l,0); + ai.condition:=C_GEU; + list.concat(ai); + end; + + a_call_name(list,'FPC_OVERFLOW',false); + a_label(list,l); + end; + OP_IMUL: + begin + { No overflow if upper result is same as sign of result } + current_asmdata.getjumplabel(l); + + tmpreg:=getintregister(list,OS_INT); + tmpreg0:=getintregister(list,OS_INT); + list.Concat(taicpu.op_reg_reg_reg(A_MUL,dst,src1,src2)); + list.Concat(taicpu.op_reg_reg_reg(A_MULH,tmpreg,src1,src2)); + + list.concat(taicpu.op_reg_reg_const(A_SRAI,tmpreg0,dst,63)); + + a_cmp_reg_reg_label(list,OS_INT,OC_EQ,tmpreg,tmpreg0,l); + + a_call_name(list,'FPC_OVERFLOW',false); + a_label(list,l); + end; + OP_MUL: + begin + { No overflow if upper result is 0 } + current_asmdata.getjumplabel(l); + + tmpreg:=getintregister(list,OS_INT); + list.Concat(taicpu.op_reg_reg_reg(A_MUL,dst,src1,src2)); + list.Concat(taicpu.op_reg_reg_reg(A_MULHU,tmpreg,src1,src2)); + + a_cmp_reg_reg_label(list,OS_INT,OC_EQ,tmpreg,NR_X0,l); + + a_call_name(list,'FPC_OVERFLOW',false); + a_label(list,l); + end; + OP_IDIV: + begin + { Only overflow if dst is all 1's } + current_asmdata.getjumplabel(l); + + tmpreg:=getintregister(list,OS_INT); + list.Concat(taicpu.op_reg_reg_reg(A_DIV,dst,src1,src2)); + list.Concat(taicpu.op_reg_reg_const(A_ADDI,tmpreg,dst,1)); + + a_cmp_reg_reg_label(list,OS_INT,OC_NE,tmpreg,NR_X0,l); + + a_call_name(list,'FPC_OVERFLOW',false); + a_label(list,l); + end; + end + else + a_op_reg_reg_reg(list,op,size,src1,src2,dst); end; diff --git a/rtl/inc/systemh.inc b/rtl/inc/systemh.inc index 4d9f991023..1ff1432c82 100644 --- a/rtl/inc/systemh.inc +++ b/rtl/inc/systemh.inc @@ -1092,10 +1092,10 @@ function RolQWord(Const AValue : QWord;const Dist : Byte): QWord;{$ifdef SYSTEMI {$define FPC_HAS_INTERNAL_SAR_DWORD} { $endif defined(cpux86_64) or defined(cpui386) or defined(cpuarm) or defined(cpupowerpc) or defined(cpupowerpc64) or defined(cpumips) or defined(cpumipsel)} -{$if defined(cpux86_64) or defined(cpupowerpc64) or defined(cpuaarch64)} +{$if defined(cpux86_64) or defined(cpupowerpc64) or defined(cpuaarch64) or defined(cpuriscv64)} {$define FPC_HAS_INTERNAL_SAR_QWORD} {$define FPC_HAS_INTERNAL_SAR_ASSIGN_QWORD} -{$endif defined(cpux86_64) or defined(cpupowerpc64) or defined(cpuaarch64)} +{$endif defined(cpux86_64) or defined(cpupowerpc64) or defined(cpuaarch64) or defined(cpuriscv64)} {$endif FPC_HAS_INTERNAL_SAR} diff --git a/tests/tbs/tb0627b.pp b/tests/tbs/tb0627b.pp index 5475cbf8fe..d1682ef1b2 100644 --- a/tests/tbs/tb0627b.pp +++ b/tests/tbs/tb0627b.pp @@ -47,10 +47,10 @@ program tb0627b; {$define FPC_HAS_INTERNAL_SAR_DWORD} { $endif defined(cpux86_64) or defined(cpui386) or defined(cpuarm) or defined(cpupowerpc) or defined(cpupowerpc64) or defined(cpumips) or defined(cpumipsel)} -{$if defined(cpux86_64) or defined(cpupowerpc64) or defined(cpuaarch64)} +{$if defined(cpux86_64) or defined(cpupowerpc64) or defined(cpuaarch64) or defined(cpuriscv64)} {$define FPC_HAS_INTERNAL_SAR_QWORD} {$define FPC_HAS_INTERNAL_SAR_ASSIGN_QWORD} -{$endif defined(cpux86_64) or defined(cpupowerpc64) or defined(cpuaarch64)} +{$endif defined(cpux86_64) or defined(cpupowerpc64) or defined(cpuaarch64) or defined(cpuriscv64)} {$endif FPC_HAS_INTERNAL_SAR} diff --git a/tests/webtbs/tw11563.pp b/tests/webtbs/tw11563.pp index 1d03b348de..b122d1148b 100644 --- a/tests/webtbs/tw11563.pp +++ b/tests/webtbs/tw11563.pp @@ -12,6 +12,9 @@ program ExecStack; {$if defined(cpuaarch64)} ret: longint; {$endif} +{$if defined(cpuriscv64)} + ret: longint; +{$endif} {$if defined(cpui386) or defined(cpux86_64)} ret: Byte; {$endif} @@ -48,6 +51,11 @@ program ExecStack; DoNothing := proc(@ret); DoNothing; {$endif} +{$if defined(cpuriscv64)} + ret := $00008067; + DoNothing := proc(@ret); + DoNothing; +{$endif} {$if defined(cpui386) or defined(cpux86_64)} ret := $C3; DoNothing := proc(@ret);