From 73c68236b6a7943b8f5207a78e58483bf96a2737 Mon Sep 17 00:00:00 2001 From: florian Date: Sat, 21 Mar 2020 12:49:45 +0000 Subject: [PATCH] * Xtensa: completed compiler skeleton git-svn-id: trunk@44323 - --- .gitattributes | 3 + compiler/fpcdefs.inc | 2 +- compiler/options.pas | 9 + compiler/psystem.pas | 4 + compiler/systems.inc | 1 + compiler/systems.pas | 5 + compiler/xtensa/agcpugas.pas | 5 +- compiler/xtensa/cgcpu.pas | 227 ++++++++++++++++++--- compiler/xtensa/cpunode.pas | 4 +- compiler/xtensa/ncpuadd.pas | 261 ++++++++++++++++++++++++ compiler/xtensa/ncpucnv.pas | 198 ++++++++++++++++++ compiler/xtensa/ncpumat.pas | 373 ++++++++++++++++++++++++++++++++++ compiler/xtensa/racpugas.pas | 10 +- compiler/xtensa/xtensaatt.inc | 4 + compiler/xtensa/xtensaop.inc | 4 + 15 files changed, 1072 insertions(+), 38 deletions(-) create mode 100644 compiler/xtensa/ncpuadd.pas create mode 100644 compiler/xtensa/ncpucnv.pas create mode 100644 compiler/xtensa/ncpumat.pas diff --git a/.gitattributes b/.gitattributes index e9940c9ca3..f48c276ca0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1024,6 +1024,9 @@ compiler/xtensa/cpupi.pas svneol=native#text/pascal compiler/xtensa/cputarg.pas svneol=native#text/pascal compiler/xtensa/hlcgcpu.pas svneol=native#text/pascal compiler/xtensa/itcpugas.pas svneol=native#text/pascal +compiler/xtensa/ncpuadd.pas svneol=native#text/pascal +compiler/xtensa/ncpucnv.pas svneol=native#text/pascal +compiler/xtensa/ncpumat.pas svneol=native#text/pascal compiler/xtensa/racpugas.pas svneol=native#text/pascal compiler/xtensa/raxtensa.pas svneol=native#text/pascal compiler/xtensa/rgcpu.pas svneol=native#text/pascal diff --git a/compiler/fpcdefs.inc b/compiler/fpcdefs.inc index abea8460b5..bf4e147863 100644 --- a/compiler/fpcdefs.inc +++ b/compiler/fpcdefs.inc @@ -39,7 +39,7 @@ { This fake CPU is used to allow incorporation of globtype unit into utils/ppudump without any CPU specific code PM } {$ifdef generic_cpu} - {$define cpu32bit} + {$define #cpu32bit} {$define cpu32bitaddr} {$define cpu32bitalu} {$define cpuflags} diff --git a/compiler/options.pas b/compiler/options.pas index 35240c93e5..a1a265c2de 100644 --- a/compiler/options.pas +++ b/compiler/options.pas @@ -3751,6 +3751,7 @@ procedure read_arguments(cmd:TCmdStr); def_system_macro('FPC_COMP_IS_INT64'); def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT'); {$endif riscv32} + {$ifdef riscv64} def_system_macro('CPURISCV'); def_system_macro('CPURISCV64'); @@ -3760,6 +3761,14 @@ procedure read_arguments(cmd:TCmdStr); def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT'); {$endif riscv64} + {$ifdef xtensa} + def_system_macro('CPUXTENSA'); + def_system_macro('CPU32'); + def_system_macro('FPC_CURRENCY_IS_INT64'); + def_system_macro('FPC_COMP_IS_INT64'); + def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT'); + {$endif xtensa} + {$if defined(cpu8bitalu)} def_system_macro('CPUINT8'); {$elseif defined(cpu16bitalu)} diff --git a/compiler/psystem.pas b/compiler/psystem.pas index 7040bb6bb1..9df9250867 100644 --- a/compiler/psystem.pas +++ b/compiler/psystem.pas @@ -370,6 +370,10 @@ implementation create_fpu_types; s64currencytype:=corddef.create(scurrency,low(int64),high(int64),true); {$endif jvm} +{$ifdef xtensa} + create_fpu_types; + s64currencytype:=corddef.create(scurrency,low(int64),high(int64),true); +{$endif xtensa} set_default_int_types; { some other definitions } charpointertype:=cpointerdef.create(cansichartype); diff --git a/compiler/systems.inc b/compiler/systems.inc index 8060e8d80e..fc6b95e580 100644 --- a/compiler/systems.inc +++ b/compiler/systems.inc @@ -75,6 +75,7 @@ ,asmmode_i8086_intel ,asmmode_i8086_att ,asmmode_arm_gas_unified + ,asmmode_xtensa_gas ); (* IMPORTANT NOTE: diff --git a/compiler/systems.pas b/compiler/systems.pas index d79ebcecc4..0809eb2bb0 100644 --- a/compiler/systems.pas +++ b/compiler/systems.pas @@ -1110,6 +1110,11 @@ begin {$ifdef riscv64} default_target(system_riscv64_linux); {$endif riscv64} + +{$ifdef xtensa} + default_target(system_xtensa_embedded); +{$endif xtensa} + end; diff --git a/compiler/xtensa/agcpugas.pas b/compiler/xtensa/agcpugas.pas index fff09d7bf5..fcec63d52f 100644 --- a/compiler/xtensa/agcpugas.pas +++ b/compiler/xtensa/agcpugas.pas @@ -65,7 +65,7 @@ unit agcpugas; function TXtensaGNUAssembler.MakeCmdLine: TCmdStr; begin - Result:=''; + result:=inherited MakeCmdLine; end; {****************************************************************************} @@ -121,7 +121,7 @@ unit agcpugas; top_reg: getopstr:=gas_regname(o.reg); top_const: - getopstr:='#'+tostr(longint(o.val)); + getopstr:=tostr(longint(o.val)); top_ref: if o.ref^.refaddr=addr_full then begin @@ -182,3 +182,4 @@ unit agcpugas; begin RegisterAssembler(as_xtensa_gas_info,TXtensaGNUAssembler); end. + diff --git a/compiler/xtensa/cgcpu.pas b/compiler/xtensa/cgcpu.pas index 83199190ab..8e0d0820a2 100644 --- a/compiler/xtensa/cgcpu.pas +++ b/compiler/xtensa/cgcpu.pas @@ -31,10 +31,38 @@ interface aasmbase,aasmtai,aasmdata,aasmcpu, cpubase,cpuinfo, node,symconst,SymType,symdef, - rgcpu; + rgcpu, + cg64f32; type tcgcpu=class(tcg) + public + procedure init_register_allocators;override; + procedure done_register_allocators;override; + + { move instructions } + procedure a_load_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);override; + procedure a_load_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister;const ref: TReference);override; + procedure a_load_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: TReference; reg: tregister);override; + procedure a_load_const_reg(list: TAsmList; size: tcgsize; a: tcgint; reg: tregister);override; + procedure a_loadaddr_ref_reg(list: TAsmList; const ref: TReference; r: tregister);override; + + procedure a_op_reg_reg(list: TAsmList; op: topcg; size: tcgsize; src, dst: tregister);override; + procedure a_op_const_reg(list: TAsmList; op: topcg; size: tcgsize; a: tcgint; reg: tregister);override; + procedure a_op_reg_reg_reg(list: TAsmList; op: topcg; size: tcgsize; src1, src2, dst: tregister);override; + + 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 g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean);override; + procedure g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean);override; + + { comparison operations } + 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_concatcopy(list: TAsmList; const source, dest: treference; len: tcgint);override; {$ifdef dummy} protected { changes register size without adding register allocation info } @@ -46,60 +74,34 @@ interface procedure make_simple_ref(list:TAsmList; var op: tasmop; size: tcgsize; oppostfix: toppostfix; var ref: treference; preferred_newbasereg: tregister); function getfpuregister(list: TAsmList; size: Tcgsize): Tregister; override; procedure handle_reg_imm12_reg(list: TAsmList; op: Tasmop; size: tcgsize; src: tregister; a: tcgint; dst: tregister; tmpreg: tregister; setflags, usedest: boolean); - procedure init_register_allocators;override; - procedure done_register_allocators;override; function getmmregister(list:TAsmList;size:tcgsize):tregister;override; function handle_load_store(list:TAsmList; op: tasmop; size: tcgsize; oppostfix: toppostfix; reg: tregister; ref: treference):treference; - procedure a_call_name(list:TAsmList;const s:string; weak: boolean);override; - procedure a_call_reg(list:TAsmList;Reg:tregister);override; { General purpose instructions } procedure maybeadjustresult(list: TAsmList; op: topcg; size: tcgsize; dst: tregister); - procedure a_op_const_reg(list: TAsmList; op: topcg; size: tcgsize; a: tcgint; reg: tregister);override; - procedure a_op_reg_reg(list: TAsmList; op: topcg; size: tcgsize; src, dst: tregister);override; procedure a_op_const_reg_reg(list: TAsmList; op: topcg; size: tcgsize; a: tcgint; src, dst: tregister);override; - procedure a_op_reg_reg_reg(list: TAsmList; op: topcg; size: tcgsize; src1, src2, dst: tregister);override; procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: topcg; size: tcgsize; a: tcgint; src, dst: tregister; setflags : boolean; var ovloc : tlocation);override; procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: topcg; size: tcgsize; src1, src2, dst: tregister; setflags : boolean; var ovloc : tlocation);override; { move instructions } - procedure a_load_const_reg(list: TAsmList; size: tcgsize; a: tcgint; reg: tregister);override; procedure a_load_const_ref(list: TAsmList; size: tcgsize; a: tcgint; const ref: treference); override; - procedure a_load_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister;const ref: TReference);override; procedure a_load_reg_ref_unaligned(list: TAsmList; fromsize, tosize: tcgsize; register: tregister; const ref: treference); override; - procedure a_load_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: TReference; reg: tregister);override; procedure a_load_ref_reg_unaligned(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; register: tregister); override; - procedure a_load_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);override; - procedure a_loadaddr_ref_reg(list: TAsmList; const ref: TReference; r: tregister);override; { fpu move instructions (not used, all floating point is vector unit-based) } procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override; procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override; procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override; - procedure a_loadmm_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister;shuffle : pmmshuffle);override; - procedure a_loadmm_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: TReference; reg: tregister; shuffle: pmmshuffle);override; - procedure a_loadmm_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: TReference; shuffle: pmmshuffle);override; - - procedure a_loadmm_intreg_reg(list: TAsmList; fromsize, tosize: tcgsize; intreg, mmreg: tregister; shuffle: pmmshuffle); override; - procedure a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize: tcgsize; mmreg, intreg: tregister; shuffle: pmmshuffle); override; - - procedure a_opmm_reg_reg(list: TAsmList; Op: TOpCG; size: tcgsize; src, dst: tregister; shuffle: pmmshuffle); override; procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister); override; { comparison operations } procedure a_cmp_const_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);override; - 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 a_jmp_name(list: TAsmList; const s: string);override; procedure a_jmp_cond(list: TAsmList; cond: TOpCmp; l: tasmlabel);{ override;} procedure a_jmp_flags(list: TAsmList; const f: tresflags; l: tasmlabel);override; procedure g_flags2reg(list: TAsmList; size: tcgsize; const f:tresflags; reg: tregister);override; procedure g_overflowcheck(list: TAsmList; const loc: tlocation; def: tdef);override; procedure g_overflowcheck_loc(list: TAsmList; const loc: tlocation; def: tdef; ovloc: tlocation);override; - procedure g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean);override; - procedure g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean);override; procedure g_maybe_got_init(list: TAsmList); override; procedure g_restore_registers(list: TAsmList);override; procedure g_save_registers(list: TAsmList);override; procedure g_concatcopy_move(list: TAsmList; const source, dest: treference; len: tcgint); - procedure g_concatcopy(list: TAsmList; const source, dest: treference; len: tcgint);override; procedure g_adjust_self_value(list: TAsmList; procdef: tprocdef; ioffset: tcgint);override; procedure g_check_for_fpu_exception(list: TAsmList; force, clear: boolean);override; procedure g_profilecode(list: TAsmList);override; @@ -109,6 +111,18 @@ interface {$endif dummy} end; + tcg64fxtensa = class(tcg64f32) + procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override; + procedure a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);override; + procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override; + //procedure a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override; + //procedure a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override; + //procedure a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override; + //procedure a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override; + //procedure a_loadmm_intreg64_reg(list: TAsmList; mmsize: tcgsize; intreg: tregister64; mmreg: tregister);override; + //procedure a_loadmm_reg_intreg64(list: TAsmList; mmsize: tcgsize; mmreg: tregister; intreg: tregister64);override; + end; + procedure create_codegen; { const @@ -130,10 +144,158 @@ implementation paramgr,fmodule, symtable,symsym, tgobj, - procinfo,cpupi, - cg64f32; + procinfo,cpupi; - {$ifdef dummy} + procedure tcgcpu.init_register_allocators; + begin + inherited init_register_allocators; + rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE, + [RS_A2,RS_A3,RS_A4,RS_A5,RS_A6,RS_A7,RS_A8,RS_A9, + RS_A10,RS_A11,RS_A12,RS_A13,RS_A14,RS_A15],first_int_imreg,[]); + rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE, + [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7,RS_F8,RS_F9, + RS_F10,RS_F11,RS_F12,RS_F13,RS_F14,RS_F15],first_fpu_imreg,[]); + end; + + + procedure tcgcpu.done_register_allocators; + begin + rg[R_INTREGISTER].free; + rg[R_FPUREGISTER].free; + inherited done_register_allocators; + end; + + + procedure tcgcpu.a_load_reg_reg(list : TAsmList; fromsize,tosize : tcgsize; + reg1,reg2 : tregister); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcgcpu.a_load_reg_ref(list : TAsmList; fromsize,tosize : tcgsize; + reg : tregister; const ref : TReference); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcgcpu.a_load_ref_reg(list : TAsmList; fromsize,tosize : tcgsize; + const ref : TReference; reg : tregister); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcgcpu.a_load_const_reg(list : TAsmList; size : tcgsize; + a : tcgint; reg : tregister); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcgcpu.a_loadaddr_ref_reg(list : TAsmList; + const ref : TReference; r : tregister); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcgcpu.a_op_reg_reg(list : TAsmList; op : topcg; size : tcgsize; + src,dst : tregister); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcgcpu.a_op_const_reg(list : TAsmList; op : topcg; + size : tcgsize; a : tcgint; reg : tregister); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcgcpu.a_op_reg_reg_reg(list : TAsmList; op : topcg; + size : tcgsize; src1,src2,dst : tregister); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcgcpu.a_call_name(list : TAsmList; const s : string; + weak : boolean); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcgcpu.a_call_reg(list : TAsmList; Reg : tregister); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcgcpu.a_jmp_name(list : TAsmList; const s : string); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcgcpu.g_proc_entry(list : TAsmList; localsize : longint; + nostackframe : boolean); + begin + list.Concat(taicpu.op_reg_const(A_ENTRY,NR_STACK_POINTER_REG,32)); + end; + + + procedure tcgcpu.g_proc_exit(list : TAsmList; parasize : longint; + nostackframe : boolean); + begin + list.Concat(taicpu.op_none(A_RETW)); + end; + + + procedure tcgcpu.a_cmp_reg_reg_label(list : TAsmList; size : tcgsize; + cmp_op : topcmp; reg1,reg2 : tregister; l : tasmlabel); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcgcpu.a_jmp_always(list : TAsmList; l : TAsmLabel); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcgcpu.g_concatcopy(list : TAsmList; const source, + dest : treference; len : tcgint); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcg64fxtensa.a_op64_reg_reg(list : TAsmList; op : TOpCG; + size : tcgsize; regsrc,regdst : tregister64); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcg64fxtensa.a_op64_const_reg_reg(list : TAsmList; op : TOpCG; + size : tcgsize; value : int64; regsrc,regdst : tregister64); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure tcg64fxtensa.a_op64_const_reg(list : TAsmList; op : TOpCG; + size : tcgsize; value : int64; reg : tregister64); + begin + list.Concat(taicpu.op_none(A_NOP)); + end; + +{$ifdef dummy} procedure tcgaarch64.make_simple_ref(list:TAsmList; var op: tasmop; size: tcgsize; oppostfix: toppostfix; var ref: treference; preferred_newbasereg: tregister); var href: treference; @@ -2317,10 +2479,11 @@ implementation end; {$endif dummy} +{$warnings off} procedure create_codegen; begin -//!!! cg:=tcgcpu.Create; -//!!! cg64:=tcg64.Create; + cg:=tcgcpu.Create; + cg64:=tcg64fxtensa.Create; end; end. diff --git a/compiler/xtensa/cpunode.pas b/compiler/xtensa/cpunode.pas index ecee57c9fa..16466a7ca8 100644 --- a/compiler/xtensa/cpunode.pas +++ b/compiler/xtensa/cpunode.pas @@ -30,12 +30,12 @@ the behaviour of such a unit having just a USES clause! } implementation uses - ncgbas,ncgflw,ncgcal,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,ncgobjc, + ncgadd,ncginl,ncgmat,ncgbas,ncgflw,ncgcal,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,ncgobjc, { symtable } symcpu, aasmdef {$ifndef llvm} - //,ncpuadd,ncpumat,ncpumem,ncpuinl,ncpucnv,ncpuset,ncpucon + ,ncpuadd,ncpumat,ncpucnv//,ncpumem,ncpuset,ncpucon {$else llvm} llvmnode {$endif llvm} diff --git a/compiler/xtensa/ncpuadd.pas b/compiler/xtensa/ncpuadd.pas new file mode 100644 index 0000000000..720319cc16 --- /dev/null +++ b/compiler/xtensa/ncpuadd.pas @@ -0,0 +1,261 @@ +{ + Copyright (c) 2008 by Florian Klaempfl + + Code generation for add nodes on the Xtensa + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + **************************************************************************** +} +unit ncpuadd; + +{$i fpcdefs.inc} + +interface + + uses + node,ncgadd,cpubase; + + type + TCPUAddNode = class(tcgaddnode) + protected + function pass_1 : tnode;override; + procedure second_cmpordinal;override; + procedure second_cmpsmallset;override; + procedure second_cmp64bit;override; + procedure second_cmp; + end; + + implementation + + uses + globtype,systems, + cutils,verbose,globals, + symconst,symdef,paramgr, + aasmbase,aasmtai,aasmdata,aasmcpu,defutil,htypechk, + cgbase,cgutils,cgcpu, + cpuinfo,pass_1,pass_2,procinfo, + cpupara, + ncon,nset,nadd, + ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32, + hlcgobj; + +{***************************************************************************** + TAVRAddNode +*****************************************************************************} + + procedure TCPUAddNode.second_cmpsmallset; + + procedure gencmp(tmpreg1,tmpreg2 : tregister); + var + i : byte; + begin + //current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CP,tmpreg1,tmpreg2)); + //for i:=2 to tcgsize2size[left.location.size] do + // begin + // tmpreg1:=cg.GetNextReg(tmpreg1); + // tmpreg2:=cg.GetNextReg(tmpreg2); + // current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,tmpreg1,tmpreg2)); + // end; + end; + + var + tmpreg : tregister; + begin + //pass_left_right; + //location_reset(location,LOC_FLAGS,OS_NO); + //force_reg_left_right(false,false); + // + //case nodetype of + // equaln: + // begin + // gencmp(left.location.register,right.location.register); + // location.resflags:=F_EQ; + // end; + // unequaln: + // begin + // gencmp(left.location.register,right.location.register); + // location.resflags:=F_NE; + // end; + // lten, + // gten: + // begin + // if (not(nf_swapped in flags) and + // (nodetype = lten)) or + // ((nf_swapped in flags) and + // (nodetype = gten)) then + // swapleftright; + // tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,location.size); + // cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_AND,location.size, + // left.location.register,right.location.register,tmpreg); + // gencmp(tmpreg,right.location.register); + // location.resflags:=F_EQ; + // end; + // else + // internalerror(2004012401); + //end; + end; + + + procedure TCPUAddNode.second_cmp; + var + unsigned : boolean; + tmpreg1,tmpreg2 : tregister; + i : longint; + begin + pass_left_right; + force_reg_left_right(true,true); + // + //unsigned:=not(is_signed(left.resultdef)) or + // not(is_signed(right.resultdef)); + // + //if getresflags(unsigned)=F_NotPossible then + // begin + // swapleftright; + // { if we have to swap back and left is a constant, force it to a register because we cannot generate + // the needed code using a constant } + // if (left.location.loc=LOC_CONSTANT) and (left.location.value<>0) then + // hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false); + // end; + // + //if (not unsigned) and + // (right.location.loc=LOC_CONSTANT) and + // (right.location.value=0) and + // (getresflags(unsigned) in [F_LT,F_GE]) then + // begin + // { This is a simple sign test, where we can just test the msb } + // tmpreg1:=left.location.register; + // for i:=2 to tcgsize2size[left.location.size] do + // begin + // if i=5 then + // tmpreg1:=left.location.registerhi + // else + // tmpreg1:=cg.GetNextReg(tmpreg1); + // end; + // + // current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CP,tmpreg1,GetDefaultZeroReg)); + // + // location_reset(location,LOC_FLAGS,OS_NO); + // location.resflags:=getresflags(unsigned); + // + // exit; + // end; + // + //if right.location.loc=LOC_CONSTANT then + // begin + // { decrease register pressure on registers >= r16 } + // if (right.location.value and $ff)=0 then + // current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CP,left.location.register,GetDefaultZeroReg)) + // else + // begin + // cg.getcpuregister(current_asmdata.CurrAsmList,NR_R26); + // current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LDI,NR_R26,right.location.value and $ff)); + // current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CP,left.location.register,NR_R26)); + // cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R26); + // end; + // end + //{ on the left side, we allow only a constant if it is 0 } + //else if (left.location.loc=LOC_CONSTANT) and (left.location.value=0) then + // current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CP,GetDefaultZeroReg,right.location.register)) + //else + // current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CP,left.location.register,right.location.register)); + // + //tmpreg1:=left.location.register; + //tmpreg2:=right.location.register; + // + //for i:=2 to tcgsize2size[left.location.size] do + // begin + // if i=5 then + // begin + // if left.location.loc<>LOC_CONSTANT then + // tmpreg1:=left.location.registerhi; + // if right.location.loc<>LOC_CONSTANT then + // tmpreg2:=right.location.registerhi; + // end + // else + // begin + // if left.location.loc<>LOC_CONSTANT then + // tmpreg1:=cg.GetNextReg(tmpreg1); + // if right.location.loc<>LOC_CONSTANT then + // tmpreg2:=cg.GetNextReg(tmpreg2); + // end; + // if right.location.loc=LOC_CONSTANT then + // begin + // { just use R1? } + // if ((right.location.value64 shr ((i-1)*8)) and $ff)=0 then + // current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,tmpreg1,GetDefaultZeroReg)) + // else + // begin + // tmpreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_8); + // cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_8,(right.location.value64 shr ((i-1)*8)) and $ff,tmpreg2); + // current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,tmpreg1,tmpreg2)); + // end; + // end + // { above it is checked, if left=0, then a constant is allowed } + // else if (left.location.loc=LOC_CONSTANT) and (left.location.value=0) then + // current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,GetDefaultZeroReg,tmpreg2)) + // else + // current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,tmpreg1,tmpreg2)); + // end; + // + //location_reset(location,LOC_FLAGS,OS_NO); + //location.resflags:=getresflags(unsigned); + location.loc:=LOC_REGISTER; + current_asmdata.CurrAsmList.Concat(taicpu.op_none(A_NOP)); + end; + + + procedure TCPUAddNode.second_cmp64bit; + begin + second_cmp; + location.loc:=LOC_REGISTER; + end; + + + function TCPUAddNode.pass_1 : tnode; + begin + result:=inherited pass_1; +{$ifdef dummy} + if not(assigned(result)) then + begin + unsigned:=not(is_signed(left.resultdef)) or + not(is_signed(right.resultdef)); + + if is_64bit(left.resultdef) and + ((nodetype in [equaln,unequaln]) or + (unsigned and (nodetype in [ltn,lten,gtn,gten])) + ) then + expectloc:=LOC_FLAGS; + end; + { handling boolean expressions } + if not(assigned(result)) and + ( + not(is_boolean(left.resultdef)) or + not(is_boolean(right.resultdef)) or + is_dynamic_array(left.resultdef) + ) then + expectloc:=LOC_FLAGS; +{$endif dummy} + end; + + + procedure TCPUAddNode.second_cmpordinal; + begin + second_cmp; + end; + +begin + caddnode:=tcpuaddnode; +end. diff --git a/compiler/xtensa/ncpucnv.pas b/compiler/xtensa/ncpucnv.pas new file mode 100644 index 0000000000..ad81854149 --- /dev/null +++ b/compiler/xtensa/ncpucnv.pas @@ -0,0 +1,198 @@ +{ + Copyright (c) 1998-2002 by Florian Klaempfl + + Generate Xtensa assembler for type converting nodes + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + **************************************************************************** +} +unit ncpucnv; + +{$i fpcdefs.inc} + +interface + + uses + node,ncnv,ncgcnv; + + type + tcputypeconvnode = class(tcgtypeconvnode) + protected + // function first_int_to_real: tnode;override; + // function first_real_to_real: tnode; override; + { procedure second_int_to_int;override; } + { procedure second_string_to_string;override; } + { procedure second_cstring_to_pchar;override; } + { procedure second_string_to_chararray;override; } + { procedure second_array_to_pointer;override; } + // function first_int_to_real: tnode; override; + { procedure second_pointer_to_array;override; } + { procedure second_chararray_to_string;override; } + { procedure second_char_to_string;override; } + // procedure second_int_to_real;override; + // procedure second_real_to_real;override; + { procedure second_cord_to_pointer;override; } + { procedure second_proc_to_procvar;override; } + { procedure second_bool_to_int;override; } + procedure second_int_to_bool;override; + { procedure second_load_smallset;override; } + { procedure second_ansistring_to_pchar;override; } + { procedure second_pchar_to_string;override; } + { procedure second_class_to_intf;override; } + { procedure second_char_to_char;override; } + end; + +implementation + + uses + verbose,globtype,globals,symdef,aasmbase,aasmtai,aasmdata,symtable, + defutil, + cgbase,cgutils, + pass_1,pass_2,procinfo,ncal, + ncgutil, + cpubase,cpuinfo,aasmcpu,cgobj,hlcgobj,cgcpu; + + +{***************************************************************************** + FirstTypeConv +*****************************************************************************} + + procedure tcputypeconvnode.second_int_to_bool; + var + hreg1, + hregister : tregister; + href : treference; + resflags : tresflags; + hlabel : tasmlabel; + newsize : tcgsize; + begin +// secondpass(left); +// if codegenerror then +// exit; +// +// { Explicit typecasts from any ordinal type to a boolean type } +// { must not change the ordinal value } +// if (nf_explicit in flags) and +// not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then +// begin +// location_copy(location,left.location); +// newsize:=def_cgsize(resultdef); +// { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend } +// if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or +// ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then +// hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true) +// else +// location.size:=newsize; +// exit; +// end; +// +// { Load left node into flag F_NE/F_E } +// resflags:=F_NE; +// +// if (left.location.loc in [LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF]) then +// hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true); +// +// case left.location.loc of +// LOC_CREFERENCE, +// LOC_REFERENCE : +// begin +// if left.location.size in [OS_64,OS_S64] then +// begin +// hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT); +// cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.reference,hregister); +// href:=left.location.reference; +// inc(href.offset,4); +// tbasecgarm(cg).cgsetflags:=true; +// cg.a_op_ref_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,href,hregister); +// tbasecgarm(cg).cgsetflags:=false; +// end +// else +// begin +// hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true); +// tbasecgarm(cg).cgsetflags:=true; +// cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register); +// tbasecgarm(cg).cgsetflags:=false; +// end; +// end; +// LOC_FLAGS : +// begin +// resflags:=left.location.resflags; +// end; +// LOC_REGISTER,LOC_CREGISTER : +// begin +// if left.location.size in [OS_64,OS_S64] then +// begin +// hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32); +// cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.register64.reglo,hregister); +// tbasecgarm(cg).cgsetflags:=true; +// cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reghi,hregister); +// tbasecgarm(cg).cgsetflags:=false; +// end +// else +// begin +// tbasecgarm(cg).cgsetflags:=true; +// cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register); +// tbasecgarm(cg).cgsetflags:=false; +// end; +// end; +// LOC_JUMP : +// begin +// hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT); +// current_asmdata.getjumplabel(hlabel); +// cg.a_label(current_asmdata.CurrAsmList,left.location.truelabel); +// cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,1,hregister); +// cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel); +// cg.a_label(current_asmdata.CurrAsmList,left.location.falselabel); +// cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,0,hregister); +// cg.a_label(current_asmdata.CurrAsmList,hlabel); +// tbasecgarm(cg).cgsetflags:=true; +// cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT,hregister,hregister); +// tbasecgarm(cg).cgsetflags:=false; +// end; +// else +// internalerror(200311301); +// end; +// { load flags to register } +// location_reset(location,LOC_REGISTER,def_cgsize(resultdef)); +// hreg1:=cg.getintregister(current_asmdata.CurrAsmList,location.size); +// cg.g_flags2reg(current_asmdata.CurrAsmList,location.size,resflags,hreg1); +// cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS); +// if (is_cbool(resultdef)) then +// cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,location.size,hreg1,hreg1); +// +//{$ifndef cpu64bitalu} +// if (location.size in [OS_64,OS_S64]) then +// begin +// location.register64.reglo:=hreg1; +// location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32); +// if (is_cbool(resultdef)) then +// { reglo is either 0 or -1 -> reghi has to become the same } +// cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,location.register64.reglo,location.register64.reghi) +// else +// { unsigned } +// cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,location.register64.reghi); +// end +// else +//{$endif cpu64bitalu} +// location.register:=hreg1; + location.loc:=LOC_REGISTER; + current_asmdata.CurrAsmList.Concat(taicpu.op_none(A_NOP)); + end; + + +begin + ctypeconvnode:=tcputypeconvnode; +end. diff --git a/compiler/xtensa/ncpumat.pas b/compiler/xtensa/ncpumat.pas new file mode 100644 index 0000000000..ad088862fb --- /dev/null +++ b/compiler/xtensa/ncpumat.pas @@ -0,0 +1,373 @@ +{ + Copyright (c) 1998-2002 by Florian Klaempfl + + Generate Xtensa assembler for math nodes + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + **************************************************************************** +} +unit ncpumat; + +{$i fpcdefs.inc} + +interface + + uses + node,nmat,ncgmat; + + type + tcpumoddivnode = class(tmoddivnode) + procedure pass_generate_code;override; + end; + + tcpunotnode = class(tcgnotnode) + procedure second_boolean;override; + end; + + tcpuunaryminusnode = class(tcgunaryminusnode) + function pass_1: tnode; override; + procedure second_float;override; + end; + + tcpushlshrnode = class(tcgshlshrnode) + procedure second_64bit;override; + end; + +implementation + + uses + globtype,compinnr, + cutils,verbose,globals,constexp, + aasmbase,aasmcpu,aasmtai,aasmdata, + defutil, + symtype,symconst,symtable, + cgbase,cgobj,hlcgobj,cgutils, + pass_2,procinfo, + ncon,ncnv,ncal,ninl, + cpubase,cpuinfo, + ncgutil, + nadd,pass_1,symdef; + +{***************************************************************************** + TCPUMODDIVNODE +*****************************************************************************} + + procedure tcpumoddivnode.pass_generate_code; + begin + location.loc:=LOC_REGISTER; + end; + +{***************************************************************************** + TCPUNOTNODE +*****************************************************************************} + + procedure tcpunotnode.second_boolean; + var + tmpreg : TRegister; + begin + location.loc:=LOC_REGISTER; + //{ if the location is LOC_JUMP, we do the secondpass after the + // labels are allocated + //} + //if not handle_locjump then + // begin + // secondpass(left); + // case left.location.loc of + // LOC_FLAGS : + // begin + // location_copy(location,left.location); + // inverse_flags(location.resflags); + // end; + // LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE, + // LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF : + // begin + // hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true); + // cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS); + // if is_64bit(resultdef) then + // begin + // tmpreg:=cg.GetIntRegister(current_asmdata.CurrAsmList,OS_INT); + // { OR low and high parts together } + // current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ORR,tmpreg,left.location.register64.reglo,left.location.register64.reghi),PF_S)); + // end + // else + // current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,left.location.register,0)); + // location_reset(location,LOC_FLAGS,OS_NO); + // location.resflags:=F_EQ; + // end; + // else + // internalerror(2003042401); + // end; + // end; + end; + +{***************************************************************************** + TARMUNARYMINUSNODE +*****************************************************************************} + + function tcpuunaryminusnode.pass_1: tnode; + var + procname: string[31]; + fdef : tdef; + begin + Result:=nil; + //if (current_settings.fputype=fpu_soft) and + // (left.resultdef.typ=floatdef) then + // begin + // result:=nil; + // firstpass(left); + // expectloc:=LOC_REGISTER; + // exit; + // end; + // + //if not(FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[current_settings.fputype]) or + // (tfloatdef(resultdef).floattype=s32real) then + // exit(inherited pass_1); + // + //result:=nil; + //firstpass(left); + //if codegenerror then + // exit; + // + //if (left.resultdef.typ=floatdef) then + // begin + // case tfloatdef(resultdef).floattype of + // s64real: + // begin + // procname:='float64_sub'; + // fdef:=search_system_type('FLOAT64').typedef; + // end; + // else + // internalerror(2005082801); + // end; + // result:=ctypeconvnode.create_internal(ccallnode.createintern(procname,ccallparanode.create( + // ctypeconvnode.create_internal(left,fDef), + // ccallparanode.create(ctypeconvnode.create_internal(crealconstnode.create(0,resultdef),fdef),nil))),resultdef); + // + // left:=nil; + // end + //else + // begin + // if (left.resultdef.typ=floatdef) then + // expectloc:=LOC_FPUREGISTER + // else if (left.resultdef.typ=orddef) then + // expectloc:=LOC_REGISTER; + // end; + end; + + procedure tcpuunaryminusnode.second_float; + begin + //secondpass(left); + //case current_settings.fputype of + // fpu_fpa, + // fpu_fpa10, + // fpu_fpa11: + // begin + // hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,false); + // location:=left.location; + // current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_const(A_RSF, + // location.register,left.location.register,0), + // cgsize2fpuoppostfix[def_cgsize(resultdef)])); + // end; + // fpu_soft: + // begin + // hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false); + // location:=left.location; + // case location.size of + // OS_32: + // cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_XOR,OS_32,tcgint($80000000),location.register); + // OS_64: + // cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_XOR,OS_32,tcgint($80000000),location.registerhi); + // else + // internalerror(2014033101); + // end; + // end + // else if FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[init_settings.fputype] then + // begin + // hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true); + // location:=left.location; + // if (left.location.loc=LOC_CMMREGISTER) then + // location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size); + // + // if (tfloatdef(left.resultdef).floattype=s32real) then + // pf:=PF_F32 + // else + // pf:=PF_F64; + // + // current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VNEG, + // location.register,left.location.register), pf)); + // cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList); + // end + // else if FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[init_settings.fputype] then + // begin + // hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true); + // location:=left.location; + // if (left.location.loc=LOC_CMMREGISTER) then + // location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size); + // current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VNEG, + // location.register,left.location.register), PF_F32)); + // cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList); + // end + // else + // internalerror(2009112602); + //end; + end; + + procedure tcpushlshrnode.second_64bit; + var + v : TConstExprInt; + so: tshifterop; + lreg, resreg: TRegister64; + + procedure emit_instr(p: tai); + begin + current_asmdata.CurrAsmList.concat(p); + end; + + {This code is build like it gets called with sm=SM_LSR all the time, for SM_LSL dst* and src* have to be reversed + This will generate + mov shiftval1, shiftval + cmp shiftval1, #64 + movcs shiftval1, #64 + rsb shiftval2, shiftval1, #32 + mov dstlo, srclo, lsr shiftval1 + mov dsthi, srchi, lsr shiftval1 + orr dstlo, srchi, lsl shiftval2 + subs shiftval2, shiftval1, #32 + movpl dstlo, srchi, lsr shiftval2 + } + procedure shift_by_variable(srchi, srclo, dsthi, dstlo, shiftval: TRegister; sm: TShiftMode); + var + shiftval1,shiftval2:TRegister; + begin + //shifterop_reset(so); + //shiftval1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT); + //shiftval2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT); + // + //cg.a_load_reg_reg(current_asmdata.CurrAsmList, OS_INT, OS_INT, shiftval, shiftval1); + // + //{The ARM barrel shifter only considers the lower 8 bits of a register for the shift} + //cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS); + //emit_instr(taicpu.op_reg_const(A_CMP, shiftval1, 64)); + //emit_instr(setcondition(taicpu.op_reg_const(A_MOV, shiftval1, 64), C_CS)); + //cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS); + // + //{Calculate how much the upper register needs to be shifted left} + //emit_instr(taicpu.op_reg_reg_const(A_RSB, shiftval2, shiftval1, 32)); + // + //so.shiftmode:=sm; + //so.rs:=shiftval1; + // + //{Shift and zerofill the hi+lo register} + //emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, dstlo, srclo, so)); + //emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, dsthi, srchi, so)); + // + //{Fold in the lower 32-shiftval bits} + //if sm = SM_LSR then so.shiftmode:=SM_LSL else so.shiftmode:=SM_LSR; + //so.rs:=shiftval2; + //emit_instr(taicpu.op_reg_reg_reg_shifterop(A_ORR, dstlo, dstlo, srchi, so)); + // + //cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS); + //emit_instr(setoppostfix(taicpu.op_reg_reg_const(A_SUB, shiftval2, shiftval1, 32), PF_S)); + // + //so.shiftmode:=sm; + //emit_instr(setcondition(taicpu.op_reg_reg_shifterop(A_MOV, dstlo, srchi, so), C_PL)); + //cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS); + end; + + begin + //if GenerateThumbCode or GenerateThumb2Code then + //begin + // inherited; + // exit; + //end; + // + location_reset(location,LOC_REGISTER,def_cgsize(resultdef)); + //location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT); + //location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT); + // + //{ load left operator in a register } + //if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or + // (left.location.size<>OS_64) then + // hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,true); + // + //lreg := left.location.register64; + //resreg := location.register64; + //shifterop_reset(so); + // + //{ shifting by a constant directly coded: } + //if (right.nodetype=ordconstn) then + // begin + // v:=Tordconstnode(right).value and 63; + // {Single bit shift} + // if v = 1 then + // if nodetype=shln then + // begin + // {Shift left by one by 2 simple 32bit additions} + // cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS); + // emit_instr(setoppostfix(taicpu.op_reg_reg_reg(A_ADD, resreg.reglo, lreg.reglo, lreg.reglo), PF_S)); + // emit_instr(taicpu.op_reg_reg_reg(A_ADC, resreg.reghi, lreg.reghi, lreg.reghi)); + // cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS); + // end + // else + // begin + // {Shift right by first shifting hi by one and then using RRX (rotate right extended), which rotates through the carry} + // shifterop_reset(so); so.shiftmode:=SM_LSR; so.shiftimm:=1; + // cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS); + // emit_instr(setoppostfix(taicpu.op_reg_reg_shifterop(A_MOV, resreg.reghi, lreg.reghi, so), PF_S)); + // so.shiftmode:=SM_RRX; so.shiftimm:=0; {RRX does NOT have a shift amount} + // emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, resreg.reglo, lreg.reglo, so)); + // cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS); + // end + // {Clear one register and use the cg to generate a normal 32-bit shift} + // else if v >= 32 then + // if nodetype=shln then + // begin + // emit_instr(taicpu.op_reg_const(A_MOV, resreg.reglo, 0)); + // cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_32,v.uvalue-32,lreg.reglo,resreg.reghi); + // end + // else + // begin + // emit_instr(taicpu.op_reg_const(A_MOV, resreg.reghi, 0)); + // cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_32,v.uvalue-32,lreg.reghi,resreg.reglo); + // end + // {Shift LESS than 32, thats the tricky one} + // else if (v < 32) and (v > 1) then + // if nodetype=shln then + // shift_less_than_32(lreg.reglo, lreg.reghi, resreg.reglo, resreg.reghi, v.uvalue, SM_LSL) + // else + // shift_less_than_32(lreg.reghi, lreg.reglo, resreg.reghi, resreg.reglo, v.uvalue, SM_LSR); + // end + //else + // begin + // { force right operator into a register } + // if not(right.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or + // (right.location.size<>OS_32) then + // hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,u32inttype,true); + // + // if nodetype = shln then + // shift_by_variable(lreg.reglo, lreg.reghi, resreg.reglo, resreg.reghi, right.location.register, SM_LSL) + // else + // shift_by_variable(lreg.reghi, lreg.reglo, resreg.reghi, resreg.reglo, right.location.register, SM_LSR); + // end; + end; + + +begin + cmoddivnode:=tcpumoddivnode; + cnotnode:=tcpunotnode; + cunaryminusnode:=tcpuunaryminusnode; + cshlshrnode:=tcpushlshrnode; +end. diff --git a/compiler/xtensa/racpugas.pas b/compiler/xtensa/racpugas.pas index 04e0b1c1bb..1df6aef793 100644 --- a/compiler/xtensa/racpugas.pas +++ b/compiler/xtensa/racpugas.pas @@ -1024,12 +1024,20 @@ Unit racpugas; const asmmode_xtensa_att_info : tasmmodeinfo = ( - id : asmmode_arm_gas; + id : asmmode_xtensa_gas; idtxt : 'DIVIDED'; casmreader : txtensaattreader; ); + asmmode_xtensa_standard_info : tasmmodeinfo = + ( + id : asmmode_standard; + idtxt : 'STANDARD'; + casmreader : txtensaattreader; + ); + initialization RegisterAsmMode(asmmode_xtensa_att_info); + RegisterAsmMode(asmmode_xtensa_standard_info); end. diff --git a/compiler/xtensa/xtensaatt.inc b/compiler/xtensa/xtensaatt.inc index a2c8d13919..ea49fa1b94 100644 --- a/compiler/xtensa/xtensaatt.inc +++ b/compiler/xtensa/xtensaatt.inc @@ -10,12 +10,16 @@ 'callx4', 'callx8', 'callx12', +'entry', 'l32i', 'lsi', 'j', 'mov', 'mov.s', +'movi', 'nop', +'ret', +'retw', 's32i', 'ssi' ); diff --git a/compiler/xtensa/xtensaop.inc b/compiler/xtensa/xtensaop.inc index 9cac136cc3..45b5b969ee 100644 --- a/compiler/xtensa/xtensaop.inc +++ b/compiler/xtensa/xtensaop.inc @@ -10,12 +10,16 @@ A_CALLX0, A_CALLX4, A_CALLX8, A_CALLX12, +A_ENTRY, A_L32I, A_LSI, A_J, A_MOV, A_MOV_S, +A_MOVI, A_NOP, +A_RET, +A_RETW, A_S32I, A_SSI );