+ support for the different flag registers of sparc

* fixing 64 bit cmp operations on sparc64

git-svn-id: trunk@36638 -
This commit is contained in:
florian 2017-07-03 20:49:05 +00:00
parent 4b30e5ee11
commit 28cfa838b5
5 changed files with 128 additions and 76 deletions

View File

@ -217,6 +217,9 @@ interface
resflags.reg1:=NR_NO;
resflags.reg2:=NR_NO;
resflags.cond:=OC_NONE;
{$elseif defined(sparcgen)}
{ Load left node into flag F_NE/F_E }
resflags.Init(NR_ICC,F_NE);
{$else}
{ Load left node into flag F_NE/F_E }
resflags:=F_NE;

View File

@ -741,7 +741,7 @@ implementation
list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
list.concat(taicpu.op_reg_reg(A_CMP,NR_G0,tmpreg1));
ovloc.loc:=LOC_FLAGS;
ovloc.resflags:=F_NE;
ovloc.resflags.Init(NR_ICC,F_NE);
end;
OP_IMUL:
begin
@ -751,7 +751,7 @@ implementation
list.concat(taicpu.op_reg_const_reg(A_SRA,dst,31,tmpreg2));
list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2));
ovloc.loc:=LOC_FLAGS;
ovloc.resflags:=F_NE;
ovloc.resflags.Init(NR_ICC,F_NE);
end;
end;
end
@ -776,7 +776,7 @@ implementation
list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
list.concat(taicpu.op_reg_reg(A_CMP,NR_G0,tmpreg1));
ovloc.loc:=LOC_FLAGS;
ovloc.resflags:=F_NE;
ovloc.resflags.Init(NR_ICC,F_NE);
end;
OP_IMUL:
begin
@ -786,7 +786,7 @@ implementation
list.concat(taicpu.op_reg_const_reg(A_SRL,dst,31,tmpreg2));
list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2));
ovloc.loc:=LOC_FLAGS;
ovloc.resflags:=F_NE;
ovloc.resflags.Init(NR_ICC,F_NE);
end;
end;
end
@ -847,7 +847,18 @@ implementation
var
ai : taicpu;
begin
ai:=Taicpu.op_sym(A_Bxx,l);
case f.FlagReg of
{$ifdef SPARC64}
NR_XCC:
ai:=Taicpu.op_reg_sym(A_Bxx,f.FlagReg,l);
{$endif SPARC64}
NR_ICC:
ai:=Taicpu.op_sym(A_Bxx,l);
NR_FCC0:
ai:=Taicpu.op_sym(A_FBxx,l);
NR_FCC1,NR_FCC2,NR_FCC3:
ai:=Taicpu.op_reg_sym(A_FBxx,f.FlagReg,l);
end;
ai.SetCondition(flags_to_cond(f));
list.Concat(ai);
{ Delay slot }
@ -858,18 +869,31 @@ implementation
procedure TCGSparcGen.g_flags2reg(list:TAsmList;Size:TCgSize;const f:tresflags;reg:TRegister);
var
hl : tasmlabel;
ai : taicpu;
begin
if (f in [F_B]) then
if (f.FlagReg=NR_ICC) and (f.Flags in [F_B]) then
list.concat(taicpu.op_reg_reg_reg(A_ADDX,NR_G0,NR_G0,reg))
else if (f in [F_AE]) then
else if (f.FlagReg=NR_ICC) and (f.Flags in [F_AE]) then
list.concat(taicpu.op_reg_const_reg(A_SUBX,NR_G0,-1,reg))
else
begin
current_asmdata.getjumplabel(hl);
a_load_const_reg(list,size,1,reg);
a_jmp_flags(list,f,hl);
a_load_const_reg(list,size,0,reg);
a_label(list,hl);
if current_settings.cputype in [cpu_SPARC_V9] then
begin
ai:=Taicpu.op_reg_const_reg(A_MOVcc,f.FlagReg,0,reg);
ai.SetCondition(inverse_cond(flags_to_cond(f)));
list.Concat(ai);
ai:=Taicpu.op_reg_const_reg(A_MOVcc,f.FlagReg,1,reg);
ai.SetCondition(flags_to_cond(f));
list.Concat(ai);
end
else
begin
current_asmdata.getjumplabel(hl);
a_load_const_reg(list,size,1,reg);
a_jmp_flags(list,f,hl);
a_load_const_reg(list,size,0,reg);
a_label(list,hl);
end;
end;
end;

View File

@ -23,6 +23,8 @@ unit cpubase;
{$i fpcdefs.inc}
{$ModeSwitch advancedrecords}
interface
uses
@ -167,26 +169,32 @@ uses
*****************************************************************************}
type
TResFlags=(
{ Integer results }
F_E, {Equal}
F_NE, {Not Equal}
F_G, {Greater}
F_L, {Less}
F_GE, {Greater or Equal}
F_LE, {Less or Equal}
F_A, {Above}
F_AE, {Above or Equal, synonym: Carry Clear}
F_B, {Below, synonym: Carry Set}
F_BE, {Below or Equal}
{ Floating point results }
F_FE, {Equal}
F_FNE, {Not Equal}
F_FG, {Greater}
F_FL, {Less}
F_FGE, {Greater or Equal}
F_FLE {Less or Equal}
);
TSparcFlags = (
{ Integer results }
F_E, {Equal}
F_NE, {Not Equal}
F_G, {Greater}
F_L, {Less}
F_GE, {Greater or Equal}
F_LE, {Less or Equal}
F_A, {Above}
F_AE, {Above or Equal, synonym: Carry Clear}
F_B, {Below, synonym: Carry Set}
F_BE, {Below or Equal}
{ Floating point results }
F_FE, {Equal}
F_FNE, {Not Equal}
F_FG, {Greater}
F_FL, {Less}
F_FGE, {Greater or Equal}
F_FLE {Less or Equal}
);
TResFlags = record
{ either icc or xcc (64 bit }
FlagReg : TRegister;
Flags : TSparcFlags;
procedure Init(r : TRegister;f : TSparcFlags);
end;
{*****************************************************************************
Operand Sizes
@ -212,8 +220,6 @@ uses
fpuvarregs : Array [1..maxfpuvarregs] of TsuperRegister =
(RS_F2);
{*****************************************************************************
Default generic sizes
*****************************************************************************}
@ -395,21 +401,21 @@ implementation
procedure inverse_flags(var f: TResFlags);
const
inv_flags: array[TResFlags] of TResFlags =
inv_flags: array[TSparcFlags] of TSparcFlags =
(F_NE,F_E,F_LE,F_GE,F_L,F_G,F_BE,F_B,F_AE,F_A,
F_FNE,F_FE,F_FLE,F_FGE,F_FL,F_FG);
begin
f:=inv_flags[f];
f.Flags:=inv_flags[f.Flags];
end;
function flags_to_cond(const f:TResFlags):TAsmCond;
const
flags_2_cond:array[TResFlags] of TAsmCond=
flags_2_cond:array[TSparcFlags] of TAsmCond=
(C_E,C_NE,C_G,C_L,C_GE,C_LE,C_A,C_AE,C_B,C_BE,
C_FE,C_FNE,C_FG,C_FL,C_FGE,C_FLE);
begin
result:=flags_2_cond[f];
result:=flags_2_cond[f.Flags];
end;
@ -516,11 +522,13 @@ implementation
result := inverse[c];
end;
function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
begin
result := c1 = c2;
end;
function dwarf_reg(r:tregister):shortint;
begin
result:=regdwarf_table[findreg_by_number(r)];
@ -528,4 +536,11 @@ implementation
internalerror(200603251);
end;
procedure TResFlags.Init(r : TRegister; f : TSparcFlags);
begin
FlagReg:=r;
Flags:=f;
end;
end.

View File

@ -31,7 +31,7 @@ interface
type
tsparcaddnode = class(tcgaddnode)
private
function GetResFlags(unsigned:Boolean):TResFlags;
function GetResFlags(unsigned,use64bit:Boolean):TResFlags;
function GetFPUResFlags:TResFlags;
protected
procedure second_addfloat;override;
@ -63,39 +63,47 @@ interface
TSparcAddNode
*****************************************************************************}
function TSparcAddNode.GetResFlags(unsigned:Boolean):TResFlags;
function TSparcAddNode.GetResFlags(unsigned,use64bit:Boolean):TResFlags;
var
flagreg : TRegister;
begin
{$ifdef SPARC64}
if use64bit then
flagreg:=NR_XCC
else
{$endif SPARC64}
flagreg:=NR_ICC;
case NodeType of
equaln:
GetResFlags:=F_E;
GetResFlags.Init(flagreg,F_E);
unequaln:
GetResFlags:=F_NE;
GetResFlags.Init(flagreg,F_NE);
else
if not(unsigned) then
begin
if nf_swapped in flags then
case NodeType of
ltn:
GetResFlags:=F_G;
GetResFlags.Init(flagreg,F_G);
lten:
GetResFlags:=F_GE;
GetResFlags.Init(flagreg,F_GE);
gtn:
GetResFlags:=F_L;
GetResFlags.Init(flagreg,F_L);
gten:
GetResFlags:=F_LE;
GetResFlags.Init(flagreg,F_LE);
else
internalerror(2014082010);
end
else
case NodeType of
ltn:
GetResFlags:=F_L;
GetResFlags.Init(flagreg,F_L);
lten:
GetResFlags:=F_LE;
GetResFlags.Init(flagreg,F_LE);
gtn:
GetResFlags:=F_G;
GetResFlags.Init(flagreg,F_G);
gten:
GetResFlags:=F_GE;
GetResFlags.Init(flagreg,F_GE);
else
internalerror(2014082011);
end;
@ -105,26 +113,26 @@ interface
if nf_swapped in Flags then
case NodeType of
ltn:
GetResFlags:=F_A;
GetResFlags.Init(flagreg,F_A);
lten:
GetResFlags:=F_AE;
GetResFlags.Init(flagreg,F_AE);
gtn:
GetResFlags:=F_B;
GetResFlags.Init(flagreg,F_B);
gten:
GetResFlags:=F_BE;
GetResFlags.Init(flagreg,F_BE);
else
internalerror(2014082012);
end
else
case NodeType of
ltn:
GetResFlags:=F_B;
GetResFlags.Init(flagreg,F_B);
lten:
GetResFlags:=F_BE;
GetResFlags.Init(flagreg,F_BE);
gtn:
GetResFlags:=F_A;
GetResFlags.Init(flagreg,F_A);
gten:
GetResFlags:=F_AE;
GetResFlags.Init(flagreg,F_AE);
else
internalerror(2014082013);
end;
@ -137,34 +145,34 @@ interface
begin
case NodeType of
equaln:
result:=F_FE;
result.Init(NR_FCC0,F_FE);
unequaln:
result:=F_FNE;
result.Init(NR_FCC0,F_FNE);
else
begin
if nf_swapped in Flags then
case NodeType of
ltn:
result:=F_FG;
result.Init(NR_FCC0,F_FG);
lten:
result:=F_FGE;
result.Init(NR_FCC0,F_FGE);
gtn:
result:=F_FL;
result.Init(NR_FCC0,F_FL);
gten:
result:=F_FLE;
result.Init(NR_FCC0,F_FLE);
else
internalerror(2014082014);
end
else
case NodeType of
ltn:
result:=F_FL;
result.Init(NR_FCC0,F_FL);
lten:
result:=F_FLE;
result.Init(NR_FCC0,F_FLE);
gtn:
result:=F_FG;
result.Init(NR_FCC0,F_FG);
gten:
result:=F_FGE;
result.Init(NR_FCC0,F_FGE);
else
internalerror(2014082015);
end;
@ -268,7 +276,7 @@ interface
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBcc,left.location.register,right.location.register,NR_G0));
location_reset(location,LOC_FLAGS,OS_NO);
location.resflags:=getresflags(true);
location.resflags:=getresflags(true,is_64bit(right.resultdef));
end;
@ -287,7 +295,7 @@ interface
unequaln:
begin
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBcc,left.location.register,right.location.register,NR_G0));
location.resflags:=getresflags(true);
location.resflags:=getresflags(true,is_64bit(right.resultdef));
end;
lten,
gten:
@ -300,7 +308,7 @@ interface
tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_AND,left.location.register,right.location.register,tmpreg));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBcc,tmpreg,right.location.register,NR_G0));
location.resflags:=F_E;
location.resflags.Init(NR_ICC,F_E);
end;
else
internalerror(2012042701);
@ -373,7 +381,7 @@ interface
if (nodetype in [equaln,unequaln]) then
begin
location.resflags:=getresflags(unsigned);
location.resflags:=getresflags(unsigned,false);
if (right.location.loc=LOC_CONSTANT) then
begin
if hi(right.location.value64)<>0 then
@ -417,13 +425,13 @@ interface
if (nodetype in [ltn,gten]) then
begin
emit_compare(current_asmdata.CurrAsmList,left,right);
location.resflags:=getresflags(unsigned);
location.resflags:=getresflags(unsigned,false);
end
else if (nodetype in [lten,gtn]) then
begin
emit_compare(current_asmdata.CurrAsmList,right,left);
toggleflag(nf_swapped);
location.resflags:=getresflags(unsigned);
location.resflags:=getresflags(unsigned,false);
toggleflag(nf_swapped);
end
else
@ -449,7 +457,7 @@ interface
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBcc,left.location.register,right.location.register,NR_G0));
location_reset(location,LOC_FLAGS,OS_NO);
location.resflags:=getresflags(unsigned);
location.resflags:=getresflags(unsigned,is_64bit(right.resultdef));
end;
const

View File

@ -142,6 +142,7 @@ implementation
href : treference;
hregister : tregister;
l1,l2 : tasmlabel;
TempFlags : TResFlags;
begin
location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
@ -167,7 +168,8 @@ implementation
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FiTOd,location.register,location.register));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg(A_CMP,hregister,NR_G0));
cg.a_jmp_flags(current_asmdata.CurrAsmList,F_GE,l2);
TempFlags.Init(NR_ICC,F_GE);
cg.a_jmp_flags(current_asmdata.CurrAsmList,TempFlags,l2);
case tfloatdef(resultdef).floattype of
{ converting dword to s64real first and cut off at the end avoids precision loss }