From ca75588989a71b3f6ce30c71e882bfdc51c7f23f Mon Sep 17 00:00:00 2001 From: florian Date: Thu, 1 Nov 2012 17:18:25 +0000 Subject: [PATCH] + first cpubase implementation for aarch64 git-svn-id: trunk@22901 - --- .gitattributes | 1 + compiler/aarch64/a64reg.dat | 3 + compiler/aarch64/cpubase.pas | 450 +++++++++++++++++++++++++++++++++++ compiler/aarch64/ra64con.inc | 1 + compiler/aarch64/ra64dwa.inc | 3 +- compiler/aarch64/ra64nor.inc | 2 +- compiler/aarch64/ra64num.inc | 3 +- compiler/aarch64/ra64rni.inc | 3 +- compiler/aarch64/ra64sri.inc | 1 + compiler/aarch64/ra64sta.inc | 3 +- compiler/aarch64/ra64std.inc | 3 +- compiler/aarch64/ra64sup.inc | 1 + 12 files changed, 468 insertions(+), 6 deletions(-) create mode 100644 compiler/aarch64/cpubase.pas diff --git a/.gitattributes b/.gitattributes index 8ffd36cc97..2d1409fc56 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13,6 +13,7 @@ compiler/aarch64/a64nop.inc svneol=native#text/plain compiler/aarch64/a64op.inc svneol=native#text/plain compiler/aarch64/a64reg.dat svneol=native#text/plain compiler/aarch64/a64tab.inc svneol=native#text/plain +compiler/aarch64/cpubase.pas svneol=native#text/plain compiler/aarch64/cpuinfo.pas svneol=native#text/plain compiler/aarch64/ra64con.inc svneol=native#text/plain compiler/aarch64/ra64dwa.inc svneol=native#text/plain diff --git a/compiler/aarch64/a64reg.dat b/compiler/aarch64/a64reg.dat index 6336459864..f1da4aed49 100644 --- a/compiler/aarch64/a64reg.dat +++ b/compiler/aarch64/a64reg.dat @@ -233,3 +233,6 @@ H31,$04,$03,$1F,h31,31,31 S31,$04,$09,$1F,s31,31,31 D31,$04,$0a,$1F,d31,31,31 Q31,$04,$05,$1F,q31,31,31 + +NZCV,$05,$00,$00,nzcv,0,0 + diff --git a/compiler/aarch64/cpubase.pas b/compiler/aarch64/cpubase.pas new file mode 100644 index 0000000000..1261c19357 --- /dev/null +++ b/compiler/aarch64/cpubase.pas @@ -0,0 +1,450 @@ +{ + Copyright (c) 1998-2012 by Florian Klaempfl and Peter Vreman + + Contains the base types for ARM64 + + 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. + + **************************************************************************** +} +{ Base unit for processor information. This unit contains + enumerations of registers, opcodes, sizes, and other + such things which are processor specific. +} +unit cpubase; + +{$define USEINLINE} + +{$i fpcdefs.inc} + + interface + + uses + cutils,cclasses, + globtype,globals, + cpuinfo, + aasmbase, + cgbase + ; + + +{***************************************************************************** + Assembler Opcodes +*****************************************************************************} + + type + TAsmOp= {$i a64op.inc} + + { This should define the array of instructions as string } + op2strtable=array[tasmop] of string[11]; + + const + { First value of opcode enumeration } + firstop = low(tasmop); + { Last value of opcode enumeration } + lastop = high(tasmop); + +{***************************************************************************** + Registers +*****************************************************************************} + + type + { Number of registers used for indexing in tables } + tregisterindex=0..{$i ra64nor.inc}-1; + + const + { Available Superregisters } + {$i ra64sup.inc} + + R_SUBWHOLE = R_SUBQ; + + { Available Registers } + {$i ra64con.inc} + + { Integer Super registers first and last } + first_int_supreg = RS_X0; + first_int_imreg = $20; + + { Integer Super registers first and last } + first_fpu_supreg = RS_S0; + first_fpu_imreg = $20; + + { MM Super register first and last } + first_mm_supreg = RS_S0; + first_mm_imreg = $20; + +{ TODO: Calculate bsstart} + regnumber_count_bsstart = 64; + + regnumber_table : array[tregisterindex] of tregister = ( + {$i ra64num.inc} + ); + + regstabs_table : array[tregisterindex] of shortint = ( + {$i ra64sta.inc} + ); + + regdwarf_table : array[tregisterindex] of shortint = ( + {$i ra64dwa.inc} + ); + { registers which may be destroyed by calls } + VOLATILE_INTREGISTERS = [RS_X0..RS_X18,RS_X29..RS_X30]; + VOLATILE_MMREGISTERS = [RS_D0..RS_D7,RS_D16..RS_D31]; + + type + totherregisterset = set of tregisterindex; + +{***************************************************************************** + Instruction post fixes +*****************************************************************************} + type + { ARM instructions load/store and arithmetic instructions + can have several instruction post fixes which are collected + in this enumeration + } + TOpPostfix = (PF_None, + { update condition flags } + PF_S, + { load/store } + PF_B,PF_SB,PF_H,PF_SH + ); + + TOpPostfixes = set of TOpPostfix; + + const + oppostfix2str : array[TOpPostfix] of string[2] = ('', + 's', + 'b','sb','h','sh'); + +{***************************************************************************** + Conditions +*****************************************************************************} + + type + TAsmCond=(C_None, + C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS, + C_GE,C_LT,C_GT,C_LE,C_AL,C_NV + ); + + TAsmConds = set of TAsmCond; + + const + cond2str : array[TAsmCond] of string[2]=('', + 'eq','ne','cs','cc','mi','pl','vs','vc','hi','ls', + 'ge','lt','gt','le','al','nv' + ); + + uppercond2str : array[TAsmCond] of string[2]=('', + 'EQ','NE','CS','CC','MI','PL','VS','VC','HI','LS', + 'GE','LT','GT','LE','AL','NV' + ); + +{***************************************************************************** + Flags +*****************************************************************************} + + type + TResFlags = (F_EQ,F_NE,F_CS,F_CC,F_MI,F_PL,F_VS,F_VC,F_HI,F_LS, + F_GE,F_LT,F_GT,F_LE); + +{***************************************************************************** + Operands +*****************************************************************************} + + taddressmode = (AM_OFFSET,AM_PREINDEXED,AM_POSTINDEXED); + tshiftmode = (SM_None,SM_LSL,SM_LSR,SM_ASR,SM_ROR,SM_RRX); + + tupdatereg = (UR_None,UR_Update); + + pshifterop = ^tshifterop; + + tshifterop = record + shiftmode : tshiftmode; + rs : tregister; + shiftimm : byte; + end; + + tcpumodeflag = (mfA, mfI, mfF); + tcpumodeflags = set of tcpumodeflag; + + tspecialregflag = (srC, srX, srS, srF); + tspecialregflags = set of tspecialregflag; + +{***************************************************************************** + Constants +*****************************************************************************} + + const + max_operands = 6; + + maxintregs = 15; + maxfpuregs = 8; + maxaddrregs = 0; + +{***************************************************************************** + Operand Sizes +*****************************************************************************} + + type + topsize = (S_NO, + S_B,S_W,S_L,S_BW,S_BL,S_WL, + S_IS,S_IL,S_IQ, + S_FS,S_FL,S_FX,S_D,S_Q,S_FV,S_FXX + ); + +{***************************************************************************** + Default generic sizes +*****************************************************************************} + + const + { Defines the default address size for a processor, } + OS_ADDR = OS_64; + { the natural int size for a processor, + has to match osuinttype/ossinttype as initialized in psystem } + OS_INT = OS_64; + OS_SINT = OS_S64; + { the maximum float size for a processor, } + OS_FLOAT = OS_F64; + { the size of a vector register for a processor } + OS_VECTOR = OS_M128; + +{***************************************************************************** + Generic Register names +*****************************************************************************} + + NR_SP = NR_XZR; + RS_SP = RS_XZR; + NR_WSP = NR_WZR; + RS_WSP = RS_WZR; + + { Stack pointer register } + NR_STACK_POINTER_REG = NR_SP; + RS_STACK_POINTER_REG = RS_SP; + { Frame pointer register (initialized in tarmprocinfo.init_framepointer) } + RS_FRAME_POINTER_REG: tsuperregister = RS_X29; + NR_FRAME_POINTER_REG: tregister = NR_X29; + { Register for addressing absolute data in a position independant way, + such as in PIC code. The exact meaning is ABI specific. For + further information look at GCC source : PIC_OFFSET_TABLE_REGNUM + } + NR_PIC_OFFSET_REG = NR_X18; + { Results are returned in this register (32-bit values) } + NR_FUNCTION_RETURN_REG = NR_X0; + RS_FUNCTION_RETURN_REG = RS_X0; + { The value returned from a function is available in this register } + NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG; + RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG; + + NR_FPU_RESULT_REG = NR_NO; + + NR_MM_RESULT_REG = NR_D0; + + NR_RETURN_ADDRESS_REG = NR_FUNCTION_RETURN_REG; + + { Offset where the parent framepointer is pushed } + PARENT_FRAMEPOINTER_OFFSET = 0; + + NR_DEFAULTFLAGS = NR_NZCV; + RS_DEFAULTFLAGS = RS_NZCV; + +{***************************************************************************** + GCC /ABI linking information +*****************************************************************************} + + const + { Registers which must be saved when calling a routine declared as + cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers + saved should be the ones as defined in the target ABI and / or GCC. + + This value can be deduced from the CALLED_USED_REGISTERS array in the + GCC source. + } + saved_standard_registers : array[0..9] of tsuperregister = + (RS_X19,RS_X20,RS_X21,RS_X22,RS_X23,RS_X24,RS_X25,RS_X26,RS_X27,RS_X28); + + { this is only for the generic code which is not used for this architecture } + saved_mm_registers : array[0..7] of tsuperregister = (RS_D8,RS_D9,RS_D10,RS_D11,RS_D12,RS_D13,RS_D14,RS_D15); + +{***************************************************************************** + Helpers +*****************************************************************************} + + { Returns the tcgsize corresponding with the size of reg.} + function reg_cgsize(const reg: tregister) : tcgsize; + function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister; + function is_calljmp(o:tasmop):boolean;{$ifdef USEINLINE}inline;{$endif USEINLINE} + procedure inverse_flags(var f: TResFlags); + function flags_to_cond(const f: TResFlags) : TAsmCond; + function findreg_by_number(r:Tregister):tregisterindex; + function std_regnum_search(const s:string):Tregister; + function std_regname(r:Tregister):string; + + 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} + + procedure shifterop_reset(var so : tshifterop); {$ifdef USEINLINE}inline;{$endif USEINLINE} + + function dwarf_reg(r:tregister):shortint; + + implementation + + uses + systems,rgBase,verbose; + + const + std_regname_table : TRegNameTable = ( + {$i ra64std.inc} + ); + + regnumber_index : array[tregisterindex] of tregisterindex = ( + {$i ra64rni.inc} + ); + + std_regname_index : array[tregisterindex] of tregisterindex = ( + {$i ra64sri.inc} + ); + + + function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister; + begin + case regtype of + R_MMREGISTER: + begin + case s of + OS_F32: + cgsize2subreg:=R_SUBFS; + OS_F64: + cgsize2subreg:=R_SUBFD; + else + internalerror(2009112701); + end; + end; + else + cgsize2subreg:=R_SUBWHOLE; + end; + end; + + + function reg_cgsize(const reg: tregister): tcgsize; + begin + case getregtype(reg) of + R_INTREGISTER : + reg_cgsize:=OS_32; + R_FPUREGISTER : + reg_cgsize:=OS_F80; + R_MMREGISTER : + begin + case getsubreg(reg) of + R_SUBFD, + R_SUBWHOLE: + result:=OS_F64; + R_SUBFS: + result:=OS_F32; + else + internalerror(2009112903); + end; + end; + else + internalerror(200303181); + end; + end; + + + function is_calljmp(o:tasmop):boolean;{$ifdef USEINLINE}inline;{$endif USEINLINE} + begin + { This isn't 100% perfect because the arm allows jumps also by writing to PC=R15. + To overcome this problem we simply forbid that FPC generates jumps by loading R15 } + is_calljmp:= o in [A_B,A_BLR,A_RET]; + end; + + + procedure inverse_flags(var f: TResFlags); + const + inv_flags: array[TResFlags] of TResFlags = + (F_NE,F_EQ,F_CC,F_CS,F_PL,F_MI,F_VC,F_VS,F_LS,F_HI, + F_LT,F_GE,F_LE,F_GT); + begin + f:=inv_flags[f]; + end; + + + function flags_to_cond(const f: TResFlags) : TAsmCond; + const + flag_2_cond: array[F_EQ..F_LE] of TAsmCond = + (C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS, + C_GE,C_LT,C_GT,C_LE); + begin + if f>high(flag_2_cond) then + internalerror(200112301); + result:=flag_2_cond[f]; + end; + + + function findreg_by_number(r:Tregister):tregisterindex; + begin + result:=rgBase.findreg_by_number_table(r,regnumber_index); + end; + + + function std_regnum_search(const s:string):Tregister; + begin + result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)]; + end; + + + function std_regname(r:Tregister):string; + var + p : tregisterindex; + begin + p:=findreg_by_number_table(r,regnumber_index); + if p<>0 then + result:=std_regname_table[p] + else + result:=generic_regname(r); + end; + + + procedure shifterop_reset(var so : tshifterop);{$ifdef USEINLINE}inline;{$endif USEINLINE} + begin + FillChar(so,sizeof(so),0); + end; + + + function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE} + const + inverse: array[TAsmCond] of TAsmCond=(C_None, + C_NE,C_EQ,C_CC,C_CS,C_PL,C_MI,C_VC,C_VS,C_LS,C_HI, + C_LT,C_GE,C_LE,C_GT,C_None,C_None + ); + begin + 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)]; + if result=-1 then + internalerror(200603251); + end; + + +end. diff --git a/compiler/aarch64/ra64con.inc b/compiler/aarch64/ra64con.inc index 6675db9c99..141d7a1cc4 100644 --- a/compiler/aarch64/ra64con.inc +++ b/compiler/aarch64/ra64con.inc @@ -224,3 +224,4 @@ NR_H31 = tregister($0403001F); NR_S31 = tregister($0409001F); NR_D31 = tregister($040a001F); NR_Q31 = tregister($0405001F); +NR_NZCV = tregister($05000000); diff --git a/compiler/aarch64/ra64dwa.inc b/compiler/aarch64/ra64dwa.inc index 24eaace425..1198db78e8 100644 --- a/compiler/aarch64/ra64dwa.inc +++ b/compiler/aarch64/ra64dwa.inc @@ -223,4 +223,5 @@ 31, 31, 31, -31 +31, +0 diff --git a/compiler/aarch64/ra64nor.inc b/compiler/aarch64/ra64nor.inc index 877eae6de9..cce0278c44 100644 --- a/compiler/aarch64/ra64nor.inc +++ b/compiler/aarch64/ra64nor.inc @@ -1,2 +1,2 @@ { don't edit, this file is generated from a64reg.dat } -225 +226 diff --git a/compiler/aarch64/ra64num.inc b/compiler/aarch64/ra64num.inc index 906d207c74..6cdb6b8b5b 100644 --- a/compiler/aarch64/ra64num.inc +++ b/compiler/aarch64/ra64num.inc @@ -223,4 +223,5 @@ tregister($0401001F), tregister($0403001F), tregister($0409001F), tregister($040a001F), -tregister($0405001F) +tregister($0405001F), +tregister($05000000) diff --git a/compiler/aarch64/ra64rni.inc b/compiler/aarch64/ra64rni.inc index 3128ff9043..29b24dae31 100644 --- a/compiler/aarch64/ra64rni.inc +++ b/compiler/aarch64/ra64rni.inc @@ -223,4 +223,5 @@ 208, 213, 218, -223 +223, +225 diff --git a/compiler/aarch64/ra64sri.inc b/compiler/aarch64/ra64sri.inc index 57ecf78ae4..a3e6620ea6 100644 --- a/compiler/aarch64/ra64sri.inc +++ b/compiler/aarch64/ra64sri.inc @@ -96,6 +96,7 @@ 101, 106, 111, +225, 69, 74, 119, diff --git a/compiler/aarch64/ra64sta.inc b/compiler/aarch64/ra64sta.inc index 24eaace425..1198db78e8 100644 --- a/compiler/aarch64/ra64sta.inc +++ b/compiler/aarch64/ra64sta.inc @@ -223,4 +223,5 @@ 31, 31, 31, -31 +31, +0 diff --git a/compiler/aarch64/ra64std.inc b/compiler/aarch64/ra64std.inc index 85e98c8472..039d5fff20 100644 --- a/compiler/aarch64/ra64std.inc +++ b/compiler/aarch64/ra64std.inc @@ -223,4 +223,5 @@ 'h31', 's31', 'd31', -'q31' +'q31', +'nzcv' diff --git a/compiler/aarch64/ra64sup.inc b/compiler/aarch64/ra64sup.inc index a74c22d568..730f708a13 100644 --- a/compiler/aarch64/ra64sup.inc +++ b/compiler/aarch64/ra64sup.inc @@ -224,3 +224,4 @@ RS_H31 = $1F; RS_S31 = $1F; RS_D31 = $1F; RS_Q31 = $1F; +RS_NZCV = $00;