diff --git a/compiler/options.pas b/compiler/options.pas index de64c87f5c..2ef6f6a6da 100644 --- a/compiler/options.pas +++ b/compiler/options.pas @@ -135,7 +135,8 @@ const + [system_i386_GO32V2] + [system_i386_freebsd] + [system_i386_netbsd] - + [system_i386_wdosx]; + + [system_i386_wdosx] + + [system_riscv32_linux,system_riscv64_linux]; suppported_targets_x_smallr = systems_linux + systems_solaris + [system_i386_haiku] @@ -4150,6 +4151,32 @@ begin def_system_macro('CPUTHUMB2'); {$endif arm} +{$if defined(riscv32) or defined(riscv64)} + { ARMHF defaults } + if (target_info.abi = abi_riscv_hf) then + { set default cpu type to ARMv7a for ARMHF unless specified otherwise } + begin + if not option.CPUSetExplicitly then + init_settings.cputype:=cpu_rv64imafdc; + if not option.OptCPUSetExplicitly then + init_settings.optimizecputype:=cpu_rv64imafdc; + + { Set FPU type } + if not(option.FPUSetExplicitly) then + begin + init_settings.fputype:=fpu_fd; + end + else + begin + if not (init_settings.fputype in [fpu_fd]) then + begin + Message(option_illegal_fpu_eabihf); + StopOptions(1); + end; + end; + end; +{$endif defined(riscv32) or defined(riscv64)} + {$ifdef jvm} { set default CPU type to Dalvik when targeting Android } if target_info.system=system_jvm_android32 then diff --git a/compiler/riscv/cgrv.pas b/compiler/riscv/cgrv.pas index 5a616925bf..7105207c67 100644 --- a/compiler/riscv/cgrv.pas +++ b/compiler/riscv/cgrv.pas @@ -65,6 +65,8 @@ unit cgrv; procedure g_save_registers(list: TAsmList); override; procedure g_restore_registers(list: TAsmList); override; + procedure g_profilecode(list: TAsmList); override; + { fpu move instructions } 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; @@ -432,6 +434,18 @@ unit cgrv; end; + procedure tcgrv.g_profilecode(list: TAsmList); + begin + if target_info.system in [system_riscv32_linux,system_riscv64_linux] then + begin + list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_X10,NR_RETURN_ADDRESS_REG,0)); + a_call_name(list,'_mcount',false); + end + else + internalerror(2018092201); + end; + + procedure tcgrv.a_call_reg(list : TAsmList;reg: tregister); begin list.concat(taicpu.op_reg_reg(A_JALR,NR_RETURN_ADDRESS_REG,reg)); @@ -505,7 +519,7 @@ unit cgrv; end; list.concat(taicpu.op_reg_ref(op,reg,href)); - if fromsize<>tosize then + if (fromsize<>tosize) and (not (tosize in [OS_SINT,OS_INT])) then a_load_reg_reg(list,fromsize,tosize,reg,reg); end; diff --git a/compiler/riscv64/aoptcpu.pas b/compiler/riscv64/aoptcpu.pas index 2de9f6b8a6..7e2ed6cf1a 100644 --- a/compiler/riscv64/aoptcpu.pas +++ b/compiler/riscv64/aoptcpu.pas @@ -53,6 +53,47 @@ implementation uses cutils; + function MatchInstruction(const instr: tai; const op: TAsmOps; const AConditions: TAsmConds = []): boolean; + begin + result := + (instr.typ = ait_instruction) and + (taicpu(instr).opcode in op) and + ((AConditions=[]) or (taicpu(instr).condition in AConditions)); + end; + + + function MatchInstruction(const instr: tai; const op: TAsmOp; const AConditions: TAsmConds = []): boolean; + begin + result := + (instr.typ = ait_instruction) and + (taicpu(instr).opcode = op) and + ((AConditions=[]) or (taicpu(instr).condition in AConditions)); + end; + + + function MatchOperand(const oper1: TOper; const oper2: TOper): boolean; inline; + begin + result := oper1.typ = oper2.typ; + + if result then + case oper1.typ of + top_const: + Result:=oper1.val = oper2.val; + top_reg: + Result:=oper1.reg = oper2.reg; + {top_ref: + Result:=RefsEqual(oper1.ref^, oper2.ref^);} + else Result:=false; + end + end; + + + function MatchOperand(const oper: TOper; const reg: TRegister): boolean; inline; + begin + result := (oper.typ = top_reg) and (oper.reg = reg); + end; + + {$ifdef DEBUG_AOPTCPU} procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai); begin @@ -116,6 +157,20 @@ implementation function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean; + + procedure RemoveInstr(var orig: tai; moveback: boolean = true); + var + n: tai; + begin + if moveback and (not GetLastInstruction(orig,n)) then + GetNextInstruction(orig,n); + + AsmL.Remove(orig); + orig.Free; + + orig:=n; + end; + var hp1: tai; begin @@ -129,7 +184,7 @@ implementation { Changes addi x, y, # - addi z, x, # + addi/addiw z, x, # dealloc x To addi z, y, #+# @@ -137,10 +192,9 @@ implementation if (taicpu(p).ops=3) and (taicpu(p).oper[2]^.typ=top_const) and GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and - (hp1.typ=ait_instruction) and - (taicpu(hp1).opcode=A_ADDI) and + MatchInstruction(hp1,[A_ADDI,A_ADDIW]) and (taicpu(hp1).ops=3) and - (taicpu(p).oper[0]^.reg=taicpu(hp1).oper[1]^.reg) and + MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^) and (taicpu(p).oper[2]^.typ=top_const) and is_imm12(taicpu(p).oper[2]^.val+taicpu(hp1).oper[2]^.val) and (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and @@ -151,10 +205,7 @@ implementation DebugMsg('Peephole AddiAddi2Addi performed', hp1); - GetNextInstruction(p,hp1); - AsmL.Remove(p); - p.Free; - p:=hp1; + RemoveInstr(p); result:=true; end @@ -168,10 +219,9 @@ implementation } else if (taicpu(p).ops=3) and (taicpu(p).oper[2]^.typ=top_ref) and - (taicpu(p).oper[0]^.reg=taicpu(p).oper[1]^.reg) and + MatchOperand(taicpu(p).oper[0]^,taicpu(p).oper[1]^) and GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and - (hp1.typ=ait_instruction) and - (taicpu(hp1).opcode in [A_LB,A_LBU,A_LH,A_LHU,A_LW,A_LWU,A_LD, + MatchInstruction(hp1, [A_LB,A_LBU,A_LH,A_LHU,A_LW,A_LWU,A_LD, A_SB,A_SH,A_SW,A_SD]) and (taicpu(hp1).ops=2) and (taicpu(hp1).oper[1]^.typ=top_ref) and @@ -181,15 +231,11 @@ implementation RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then begin taicpu(hp1).loadref(1,taicpu(p).oper[2]^.ref^); - taicpu(hp1).oper[1]^.ref^.base:=taicpu(p).oper[0]^.reg; + taicpu(hp1).oper[1]^.ref^.base:=taicpu(p).oper[1]^.reg; DebugMsg('Peephole AddiMem2Mem performed', hp1); - GetNextInstruction(p,hp1); - - AsmL.Remove(p); - p.Free; - p:=hp1; + RemoveInstr(p); result:=true; end; @@ -206,14 +252,10 @@ implementation } if (taicpu(p).ops=3) and GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and - (hp1.typ=ait_instruction) and - (taicpu(hp1).opcode=A_Bxx) and + MatchInstruction(hp1,A_Bxx,[C_GEU,C_EQ]) and (taicpu(hp1).ops=3) and - (taicpu(hp1).oper[0]^.typ=top_reg) and - (taicpu(hp1).oper[0]^.reg=NR_X0) and - (taicpu(hp1).oper[1]^.typ=top_reg) and - (taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) and - (taicpu(hp1).condition=C_GEU) and + MatchOperand(taicpu(hp1).oper[0]^,NR_X0) and + MatchOperand(taicpu(hp1).oper[1]^,taicpu(p).oper[0]^) and (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and (not RegModifiedBetween(taicpu(p).oper[2]^.reg, p,hp1)) and RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then @@ -222,14 +264,9 @@ implementation taicpu(hp1).loadreg(1,taicpu(p).oper[2]^.reg); taicpu(hp1).condition:=C_EQ; - DebugMsg('Peephole SubBgeu2Bne performed', hp1); + DebugMsg('Peephole SubBxx2Beq performed', hp1); - GetNextInstruction(p,hp1); - - asml.remove(p); - p.Free; - - p:=hp1; + RemoveInstr(p); result:=true; end; @@ -245,17 +282,12 @@ implementation bltu/geu X0, y, ... } if (taicpu(p).ops=3) and - (taicpu(p).oper[1]^.typ=top_reg) and - (taicpu(p).oper[1]^.reg=NR_X0) and + MatchOperand(taicpu(p).oper[1]^,NR_X0) and GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and - (hp1.typ=ait_instruction) and - (taicpu(hp1).opcode=A_Bxx) and + MatchInstruction(hp1,A_Bxx,[C_NE,C_EQ]) and (taicpu(hp1).ops=3) and - (taicpu(hp1).oper[0]^.typ=top_reg) and - (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and - (taicpu(hp1).oper[1]^.typ=top_reg) and - (taicpu(hp1).oper[1]^.reg=NR_X0) and - (taicpu(hp1).condition in [C_NE,C_EQ]) and + MatchOperand(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^) and + MatchOperand(taicpu(hp1).oper[1]^,NR_X0) and (not RegModifiedBetween(taicpu(p).oper[2]^.reg, p,hp1)) and RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then begin @@ -269,13 +301,7 @@ implementation DebugMsg('Peephole SltuB2B performed', hp1); - if not GetLastInstruction(p,hp1) then - GetNextInstruction(p,hp1); - - asml.remove(p); - p.Free; - - p:=hp1; + RemoveInstr(p); result:=true; end; @@ -294,14 +320,10 @@ implementation (taicpu(p).oper[2]^.typ=top_const) and (taicpu(p).oper[2]^.val=1) and GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and - (hp1.typ=ait_instruction) and - (taicpu(hp1).opcode=A_Bxx) and + MatchInstruction(hp1,A_Bxx,[C_NE,C_EQ]) and (taicpu(hp1).ops=3) and - (taicpu(hp1).oper[0]^.typ=top_reg) and - (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and - (taicpu(hp1).oper[1]^.typ=top_reg) and - (taicpu(hp1).oper[1]^.reg=NR_X0) and - (taicpu(hp1).condition in [C_NE,C_EQ]) and + MatchOperand(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^) and + MatchOperand(taicpu(hp1).oper[1]^,NR_X0) and (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then begin @@ -310,13 +332,7 @@ implementation DebugMsg('Peephole Sltiu0B2B performed', hp1); - if not GetLastInstruction(p,hp1) then - GetNextInstruction(p,hp1); - - asml.remove(p); - p.Free; - - p:=hp1; + RemoveInstr(p); result:=true; end; @@ -329,7 +345,7 @@ implementation beq/ne x,x0,... dealloc x Into - bne y,x0,... + bge/lt y,x0,... } if (taicpu(p).ops=3) and (taicpu(p).oper[2]^.typ=top_const) and @@ -346,28 +362,17 @@ implementation (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then begin + taicpu(hp1).loadreg(0,taicpu(p).oper[1]^.reg); + taicpu(hp1).loadreg(1,NR_X0); + if taicpu(hp1).condition=C_NE then - begin - taicpu(hp1).loadreg(0,taicpu(p).oper[1]^.reg); - taicpu(hp1).loadreg(1,NR_X0); - taicpu(hp1).condition:=C_LT; - end + taicpu(hp1).condition:=C_LT else - begin - taicpu(hp1).loadreg(0,taicpu(p).oper[1]^.reg); - taicpu(hp1).loadreg(1,NR_X0); - taicpu(hp1).condition:=C_GE; - end; + taicpu(hp1).condition:=C_GE; DebugMsg('Peephole Slti0B2B performed', hp1); - if not GetLastInstruction(p,hp1) then - GetNextInstruction(p,hp1); - - asml.remove(p); - p.Free; - - p:=hp1; + RemoveInstr(p); result:=true; end; diff --git a/compiler/riscv64/cpubase.pas b/compiler/riscv64/cpubase.pas index fb94973a13..89ce7d292a 100644 --- a/compiler/riscv64/cpubase.pas +++ b/compiler/riscv64/cpubase.pas @@ -106,6 +106,8 @@ type A_SFENCE_VM ); + TAsmOps = set of TAsmOp; + {# This should define the array of instructions as string } op2strtable = array[tasmop] of string[8]; @@ -189,6 +191,8 @@ type TAsmCond = (C_None { unconditional jumps }, C_LT,C_LTU,C_GE,C_GEU,C_NE,C_EQ); + TAsmConds = set of TAsmCond; + const cond2str: Array[TAsmCond] of string[4] = ({cf_none}'', { conditions when not using ctr decrement etc} diff --git a/compiler/systems.inc b/compiler/systems.inc index 997fb22199..3c60f4a7ce 100644 --- a/compiler/systems.inc +++ b/compiler/systems.inc @@ -315,6 +315,7 @@ ,abi_eabi,abi_armeb,abi_eabihf ,abi_old_win32_gnu ,abi_aarch64_darwin + ,abi_riscv_hf ); const diff --git a/compiler/systems.pas b/compiler/systems.pas index 7366b8de1b..349d5b0314 100644 --- a/compiler/systems.pas +++ b/compiler/systems.pas @@ -410,7 +410,8 @@ interface (name: 'ARMEB' ; supported:{$ifdef FPC_ARMEB}true{$else}false{$endif}), (name: 'EABIHF' ; supported:{$ifdef FPC_ARMHF}true{$else}false{$endif}), (name: 'OLDWIN32GNU'; supported:{$ifdef I386}true{$else}false{$endif}), - (name: 'AARCH64IOS'; supported:{$ifdef aarch64}true{$else}false{$endif}) + (name: 'AARCH64IOS'; supported:{$ifdef aarch64}true{$else}false{$endif}), + (name: 'RISCVHF'; supported:{$if defined(riscv32) or defined(riscv64)}true{$else}false{$endif}) ); var diff --git a/compiler/systems/i_linux.pas b/compiler/systems/i_linux.pas index 16fd5b8652..c65535df91 100644 --- a/compiler/systems/i_linux.pas +++ b/compiler/systems/i_linux.pas @@ -1091,7 +1091,7 @@ unit i_linux; first_parm_offset : 0; stacksize : 32*1024*1024; stackalign : 8; - abi : abi_default; + abi : abi_riscv_hf; llvmdatalayout : 'e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64'; ); @@ -1157,7 +1157,7 @@ unit i_linux; first_parm_offset : 16; stacksize : 10*1024*1024; stackalign : 16; - abi : abi_default; + abi : abi_riscv_hf; llvmdatalayout : 'E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:64:64-v128:128:128-n32:64'; );