diff --git a/compiler/ncgcnv.pas b/compiler/ncgcnv.pas index 1688a4214e..9a21f07586 100644 --- a/compiler/ncgcnv.pas +++ b/compiler/ncgcnv.pas @@ -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; diff --git a/compiler/sparcgen/cgsparc.pas b/compiler/sparcgen/cgsparc.pas index 4605d09818..95c99cca9d 100644 --- a/compiler/sparcgen/cgsparc.pas +++ b/compiler/sparcgen/cgsparc.pas @@ -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; diff --git a/compiler/sparcgen/cpubase.pas b/compiler/sparcgen/cpubase.pas index 77672c3f03..f525676e7c 100644 --- a/compiler/sparcgen/cpubase.pas +++ b/compiler/sparcgen/cpubase.pas @@ -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. diff --git a/compiler/sparcgen/ncpuadd.pas b/compiler/sparcgen/ncpuadd.pas index 1b89579d28..d7c27e32e9 100644 --- a/compiler/sparcgen/ncpuadd.pas +++ b/compiler/sparcgen/ncpuadd.pas @@ -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 diff --git a/compiler/sparcgen/ncpucnv.pas b/compiler/sparcgen/ncpucnv.pas index 52d42827aa..307ca6d3ab 100644 --- a/compiler/sparcgen/ncpucnv.pas +++ b/compiler/sparcgen/ncpucnv.pas @@ -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 }