diff options
-rw-r--r-- | riscv_new/compiler/aggas.pas | 2 | ||||
-rw-r--r-- | riscv_new/compiler/riscv/cgrv.pas | 12 | ||||
-rw-r--r-- | riscv_new/compiler/riscv64/cgcpu.pas | 233 | ||||
-rw-r--r-- | riscv_new/rtl/inc/systemh.inc | 4 | ||||
-rw-r--r-- | riscv_new/tests/tbs/tb0627b.pp | 4 | ||||
-rw-r--r-- | riscv_new/tests/webtbs/tw11563.pp | 8 |
6 files changed, 147 insertions, 116 deletions
diff --git a/riscv_new/compiler/aggas.pas b/riscv_new/compiler/aggas.pas index b84f0d505d..4478bc3dc4 100644 --- a/riscv_new/compiler/aggas.pas +++ b/riscv_new/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/riscv_new/compiler/riscv/cgrv.pas b/riscv_new/compiler/riscv/cgrv.pas index 0cbfd753c0..5a616925bf 100644 --- a/riscv_new/compiler/riscv/cgrv.pas +++ b/riscv_new/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/riscv_new/compiler/riscv64/cgcpu.pas b/riscv_new/compiler/riscv64/cgcpu.pas index 6f028d5448..554107ab91 100644 --- a/riscv_new/compiler/riscv64/cgcpu.pas +++ b/riscv_new/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=result<a - jump if t0=t1 - } - tmpreg:=getintregister(list,OS_INT); - if is_imm12(a) then - list.Concat(taicpu.op_reg_reg_const(A_SLTI,tmpreg,dst,a)) - else - begin - a_load_const_reg(list,OS_INT,a,tmpreg); - list.Concat(taicpu.op_reg_reg_reg(A_SLT,tmpreg,dst,tmpreg)); - end; - - ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,tmpreg,NR_X0,l,0); - if a<0 then - ai.condition:=C_NE - else - ai.condition:=C_EQ; - list.concat(ai); - end - else - begin - { - jump if not sum<x - } - tmpreg:=getintregister(list,OS_INT); - if size in [OS_S32,OS_32] then - begin - a_load_reg_reg(list,size,OS_64,dst,tmpreg); - dst:=tmpreg; - end; - list.Concat(taicpu.op_reg_reg_reg(A_SLTU,tmpreg,dst,src)); - - ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,tmpreg,NR_X0,l,0); - ai.condition:=C_EQ; - list.concat(ai); - end; - - a_call_name(list,'FPC_OVERFLOW',false); - a_label(list,l); - end; + a_load_const_reg(list,size,a,tmpreg); + a_op_reg_reg_reg_checkoverflow(list,op,size,tmpreg,src,dst,setflags,ovloc); + end + else + a_op_const_reg_reg(list,op,size,a,src,dst); end; @@ -262,60 +212,133 @@ implementation begin signed:=tcgsize2unsigned[size]<>size; - 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; + if setflags then + case op of + OP_ADD: + begin + current_asmdata.getjumplabel(l); - a_op_reg_reg_reg(list,op,size,src1,src2,dst); + list.Concat(taicpu.op_reg_reg_reg(A_ADD,dst,src2,src1)); - if setflags and - (op=OP_ADD) then - begin - current_asmdata.getjumplabel(l); - if signed then - begin - { - t0=src1<0 - t1=result<src1 - jump if t0=t1 - } - 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,src1)); + if signed then + begin + { + t0=src1<0 + t1=result<src2 + overflow if t0<>t1 + } + 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,tmpreg,tmpreg0,l,0); - ai.condition:=C_EQ; - list.concat(ai); - end - else + ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,dst,src2,l,0); + ai.condition:=C_GEU; + list.concat(ai); + end; + + a_call_name(list,'FPC_OVERFLOW',false); + a_label(list,l); + end; + OP_SUB: begin - { - jump if not sum<x - } - tmpreg:=getintregister(list,OS_INT); - if size in [OS_S32,OS_32] then + current_asmdata.getjumplabel(l); + + 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 - a_load_reg_reg(list,size,OS_64,dst,tmpreg); - dst:=tmpreg; + { 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_SLTU,tmpreg,dst,src2)); + list.Concat(taicpu.op_reg_reg_reg(A_MUL,dst,src1,src2)); + list.Concat(taicpu.op_reg_reg_reg(A_MULHU,tmpreg,src1,src2)); - ai:=taicpu.op_reg_reg_sym_ofs(A_Bxx,tmpreg,NR_X0,l,0); - ai.condition:=C_EQ; - list.concat(ai); + 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); - a_call_name(list,'FPC_OVERFLOW',false); - a_label(list,l); - end; + 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/riscv_new/rtl/inc/systemh.inc b/riscv_new/rtl/inc/systemh.inc index 4d9f991023..1ff1432c82 100644 --- a/riscv_new/rtl/inc/systemh.inc +++ b/riscv_new/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/riscv_new/tests/tbs/tb0627b.pp b/riscv_new/tests/tbs/tb0627b.pp index 5475cbf8fe..d1682ef1b2 100644 --- a/riscv_new/tests/tbs/tb0627b.pp +++ b/riscv_new/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/riscv_new/tests/webtbs/tw11563.pp b/riscv_new/tests/webtbs/tw11563.pp index 1d03b348de..b122d1148b 100644 --- a/riscv_new/tests/webtbs/tw11563.pp +++ b/riscv_new/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); |