mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 01:48:00 +02:00
+ 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:
parent
4b30e5ee11
commit
28cfa838b5
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
|
Loading…
Reference in New Issue
Block a user