diff --git a/compiler/fpcdefs.inc b/compiler/fpcdefs.inc index bf4e147863..3ef42f0873 100644 --- a/compiler/fpcdefs.inc +++ b/compiler/fpcdefs.inc @@ -313,6 +313,7 @@ {$define cpu32bitaddr} {$define cpu32bitalu} {$define cpufpemu} + {$define cpuflags} { xtensa has a boolean extension } {$define cputargethasfixedstack} {$define cpuneedsmulhelper} {$define cpuneedsdivhelper} diff --git a/compiler/ncgcnv.pas b/compiler/ncgcnv.pas index 2311da2f43..98b2f7dad8 100644 --- a/compiler/ncgcnv.pas +++ b/compiler/ncgcnv.pas @@ -220,6 +220,9 @@ interface {$elseif defined(sparcgen)} { Load left node into flag F_NE/F_E } resflags.Init(NR_ICC,F_NE); +{$elseif defined(xtensa)} + { Xtensa uses its own implementation } + Internalerror(2020032901); {$else} { Load left node into flag F_NE/F_E } resflags:=F_NE; diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas index ac544bf1b2..a16ee5d625 100644 --- a/compiler/ncgutil.pas +++ b/compiler/ncgutil.pas @@ -332,7 +332,11 @@ implementation LOC_FLAGS : begin cg.a_jmp_flags(list,p.location.resflags,truelabel); + + { e.g. xtensa has no default flags but uses a boolean register } +{$if defined(NR_DEFAULTFLAGS)} cg.a_reg_dealloc(list,NR_DEFAULTFLAGS); +{$endif defined(NR_DEFAULTFLAGS)} cg.a_jmp_always(list,falselabel); end; {$endif cpuflags} diff --git a/compiler/xtensa/cgcpu.pas b/compiler/xtensa/cgcpu.pas index efacf54ba4..b18759a111 100644 --- a/compiler/xtensa/cgcpu.pas +++ b/compiler/xtensa/cgcpu.pas @@ -57,7 +57,9 @@ interface procedure a_call_name(list:TAsmList;const s:string; weak: boolean);override; procedure a_call_reg(list:TAsmList;Reg:tregister);override; + procedure a_jmp_name(list: TAsmList; const s: string);override; + procedure a_jmp_flags(list: TAsmList; const f: TResFlags; l: tasmlabel);override; procedure g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean);override; procedure g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean);override; @@ -67,6 +69,8 @@ interface procedure a_cmp_reg_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);override; procedure a_jmp_always(list: TAsmList; l: TAsmLabel);override; + procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: tresflags; reg: TRegister);override; + procedure g_concatcopy(list : TAsmList; const source,dest : treference; len : tcgint);override; procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister); @@ -546,6 +550,16 @@ implementation end; + procedure tcgcpu.a_jmp_flags(list: TAsmList; const f: TResFlags; l: tasmlabel); + var + instr: taicpu; + begin + instr:=taicpu.op_reg_sym(A_Bcc,f.register,l); + instr.condition:=flags_to_cond(f.flag); + list.concat(instr); + end; + + procedure tcgcpu.g_proc_entry(list : TAsmList; localsize : longint; nostackframe : boolean); var @@ -773,6 +787,20 @@ implementation end; + procedure tcgcpu.g_flags2reg(list: TAsmList; size: TCgSize; const f: tresflags; reg: TRegister); + var + hregister: TRegister; + instr: taicpu; + begin + a_load_const_reg(list,size,0,reg); + hregister:=getintregister(list,size); + a_load_const_reg(list,size,1,hregister); + instr:=taicpu.op_reg_reg_reg(A_MOV,reg,hregister,f.register); + instr.condition:=flags_to_cond(f.flag); + list.concat(instr); + end; + + procedure tcgcpu.g_concatcopy_move(list: tasmlist; const Source, dest: treference; len: tcgint); var paraloc1, paraloc2, paraloc3: TCGPara; diff --git a/compiler/xtensa/cpubase.pas b/compiler/xtensa/cpubase.pas index 1c94a10477..1dfc3efbf5 100644 --- a/compiler/xtensa/cpubase.pas +++ b/compiler/xtensa/cpubase.pas @@ -78,7 +78,7 @@ unit cpubase; { Float Super register first and last } first_fpu_supreg = RS_F0; - first_fpu_imreg = $08; + first_fpu_imreg = $10; { MM Super register first and last } first_mm_supreg = RS_INVALID; @@ -109,18 +109,27 @@ unit cpubase; C_GE,C_LT,C_GEU,C_LTU, C_ANY,C_BNONE,C_ALL,C_NALL,C_BC,C_BS, C_EQZ,C_NEZ,C_LTZ,C_GEZ, - C_EQI,C_NEI,C_LTI,C_GEI,C_LTUI,C_GEUI + C_EQI,C_NEI,C_LTI,C_GEI,C_LTUI,C_GEUI, + C_F,C_T ); TAsmConds = set of TAsmCond; + TResFlagsEnum = (F_Z,F_NZ); + + TResFlags = record + register: TRegister; + flag: TResFlagsEnum; + end; + const cond2str : array[TAsmCond] of string[4]=('', 'eq','ne', 'ge','lt','geu','ltu', 'any','none','all','nall','bc','bs', 'eqz','nez','ltz','gez', - 'eqi','nei','lti','gei','ltui','geui' + 'eqi','nei','lti','gei','ltui','geui', + 'f','t' ); uppercond2str : array[TAsmCond] of string[4]=('', @@ -128,7 +137,8 @@ unit cpubase; 'GE','LT','GEU','LTU', 'ANY','NONE','ALL','NALL','BC','BS', 'EQZ','NEZ','LTZ','GEZ', - 'EQI','NEI','LTI','GEI','LTUI','GEUI' + 'EQI','NEI','LTI','GEI','LTUI','GEUI', + 'F','T' ); {***************************************************************************** @@ -246,6 +256,8 @@ unit cpubase; function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE} function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE} + function flags_to_cond(const f: TResFlagsEnum) : TAsmCond; + { Checks if Subset is a subset of c (e.g. "less than" is a subset of "less than or equal" } function condition_in(const Subset, c: TAsmCond): Boolean; @@ -361,13 +373,23 @@ unit cpubase; C_BNONE,C_ANY,C_NALL,C_BNONE,C_BS,C_BC, C_NEZ,C_EQZ,C_GEZ,C_LTZ, - C_NEI,C_EQI,C_GEI,C_LTI,C_GEUI,C_LTUI + C_NEI,C_EQI,C_GEI,C_LTI,C_GEUI,C_LTUI, + C_T,C_F ); begin result := inverse[c]; end; + function flags_to_cond(const f: TResFlagsEnum) : TAsmCond; + const flags2cond: array[TResFlagsEnum] of tasmcond = ( + C_F, + C_T); + begin + flags_to_cond := flags2cond[f]; + end; + + function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE} begin result := c1 = c2;