mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-06 17:08:01 +02:00
Redo overflow checking code.
Fix shift operators in case of unsigned subreg operations. There should be no sign extension here. Add some unittest implementations that test stack execution and writing to readonly constants. git-svn-id: branches/laksen/riscv_new@39762 -
This commit is contained in:
parent
f828d8700c
commit
74a7963d58
@ -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',
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
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=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));
|
||||
current_asmdata.getjumplabel(l);
|
||||
|
||||
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 not sum<x
|
||||
}
|
||||
tmpreg:=getintregister(list,OS_INT);
|
||||
if size in [OS_S32,OS_32] then
|
||||
list.Concat(taicpu.op_reg_reg_reg(A_ADD,dst,src2,src1));
|
||||
|
||||
if signed then
|
||||
begin
|
||||
a_load_reg_reg(list,size,OS_64,dst,tmpreg);
|
||||
dst:=tmpreg;
|
||||
{
|
||||
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,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;
|
||||
|
||||
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user