summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--riscv_new/compiler/aggas.pas2
-rw-r--r--riscv_new/compiler/riscv/cgrv.pas12
-rw-r--r--riscv_new/compiler/riscv64/cgcpu.pas233
-rw-r--r--riscv_new/rtl/inc/systemh.inc4
-rw-r--r--riscv_new/tests/tbs/tb0627b.pp4
-rw-r--r--riscv_new/tests/webtbs/tw11563.pp8
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);