+ 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.reg1:=NR_NO;
resflags.reg2:=NR_NO; resflags.reg2:=NR_NO;
resflags.cond:=OC_NONE; resflags.cond:=OC_NONE;
{$elseif defined(sparcgen)}
{ Load left node into flag F_NE/F_E }
resflags.Init(NR_ICC,F_NE);
{$else} {$else}
{ Load left node into flag F_NE/F_E } { Load left node into flag F_NE/F_E }
resflags:=F_NE; 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_MOV,NR_Y,tmpreg1));
list.concat(taicpu.op_reg_reg(A_CMP,NR_G0,tmpreg1)); list.concat(taicpu.op_reg_reg(A_CMP,NR_G0,tmpreg1));
ovloc.loc:=LOC_FLAGS; ovloc.loc:=LOC_FLAGS;
ovloc.resflags:=F_NE; ovloc.resflags.Init(NR_ICC,F_NE);
end; end;
OP_IMUL: OP_IMUL:
begin begin
@ -751,7 +751,7 @@ implementation
list.concat(taicpu.op_reg_const_reg(A_SRA,dst,31,tmpreg2)); list.concat(taicpu.op_reg_const_reg(A_SRA,dst,31,tmpreg2));
list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2)); list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2));
ovloc.loc:=LOC_FLAGS; ovloc.loc:=LOC_FLAGS;
ovloc.resflags:=F_NE; ovloc.resflags.Init(NR_ICC,F_NE);
end; end;
end; 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_MOV,NR_Y,tmpreg1));
list.concat(taicpu.op_reg_reg(A_CMP,NR_G0,tmpreg1)); list.concat(taicpu.op_reg_reg(A_CMP,NR_G0,tmpreg1));
ovloc.loc:=LOC_FLAGS; ovloc.loc:=LOC_FLAGS;
ovloc.resflags:=F_NE; ovloc.resflags.Init(NR_ICC,F_NE);
end; end;
OP_IMUL: OP_IMUL:
begin begin
@ -786,7 +786,7 @@ implementation
list.concat(taicpu.op_reg_const_reg(A_SRL,dst,31,tmpreg2)); list.concat(taicpu.op_reg_const_reg(A_SRL,dst,31,tmpreg2));
list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2)); list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2));
ovloc.loc:=LOC_FLAGS; ovloc.loc:=LOC_FLAGS;
ovloc.resflags:=F_NE; ovloc.resflags.Init(NR_ICC,F_NE);
end; end;
end; end;
end end
@ -847,7 +847,18 @@ implementation
var var
ai : taicpu; ai : taicpu;
begin 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)); ai.SetCondition(flags_to_cond(f));
list.Concat(ai); list.Concat(ai);
{ Delay slot } { Delay slot }
@ -858,18 +869,31 @@ implementation
procedure TCGSparcGen.g_flags2reg(list:TAsmList;Size:TCgSize;const f:tresflags;reg:TRegister); procedure TCGSparcGen.g_flags2reg(list:TAsmList;Size:TCgSize;const f:tresflags;reg:TRegister);
var var
hl : tasmlabel; hl : tasmlabel;
ai : taicpu;
begin 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)) 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)) list.concat(taicpu.op_reg_const_reg(A_SUBX,NR_G0,-1,reg))
else else
begin begin
current_asmdata.getjumplabel(hl); if current_settings.cputype in [cpu_SPARC_V9] then
a_load_const_reg(list,size,1,reg); begin
a_jmp_flags(list,f,hl); ai:=Taicpu.op_reg_const_reg(A_MOVcc,f.FlagReg,0,reg);
a_load_const_reg(list,size,0,reg); ai.SetCondition(inverse_cond(flags_to_cond(f)));
a_label(list,hl); 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;
end; end;

View File

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

View File

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

View File

@ -142,6 +142,7 @@ implementation
href : treference; href : treference;
hregister : tregister; hregister : tregister;
l1,l2 : tasmlabel; l1,l2 : tasmlabel;
TempFlags : TResFlags;
begin begin
location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef)); 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_FiTOd,location.register,location.register));
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg(A_CMP,hregister,NR_G0)); 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 case tfloatdef(resultdef).floattype of
{ converting dword to s64real first and cut off at the end avoids precision loss } { converting dword to s64real first and cut off at the end avoids precision loss }