From 03634c4038ebca7a43d385aea66a09d73504c769 Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Wed, 28 Jun 2017 07:52:12 +0200 Subject: ortho/mcode: preliminary work to support win64. --- src/ortho/mcode/ortho_code-x86-emits.adb | 64 ++++++++++++++++++-------------- src/ortho/mcode/ortho_code-x86-insns.adb | 38 ++++++++++++++----- src/ortho/mcode/ortho_code-x86.ads | 22 +++++++++-- 3 files changed, 84 insertions(+), 40 deletions(-) (limited to 'src/ortho/mcode') diff --git a/src/ortho/mcode/ortho_code-x86-emits.adb b/src/ortho/mcode/ortho_code-x86-emits.adb index 4753aab85..03c4e63a8 100644 --- a/src/ortho/mcode/ortho_code-x86-emits.adb +++ b/src/ortho/mcode/ortho_code-x86-emits.adb @@ -2821,35 +2821,31 @@ package body Ortho_Code.X86.Emits is end case; end Emit_Insn; - function Get_Preserved_Regs return O_Reg_Array is + function Get_Preserved_Regs return O_Reg_Bitmap is begin if Flags.M64 then - return Preserved_Regs_64; + if Flags.Win64 then + return Preserved_Regs_Win64; + else + return Preserved_Regs_Lin64; + end if; else return Preserved_Regs_32; end if; end Get_Preserved_Regs; -- List of registers preserved accross calls. - Preserved_Regs : constant O_Reg_Array := Get_Preserved_Regs; + Preserved_Regs : constant O_Reg_Bitmap := Get_Preserved_Regs; - procedure Push_Reg_If_Used (Reg : Regs_R64) - is - use Ortho_Code.X86.Insns; + procedure Push_Reg (Reg : Regs_R64) is begin - if Reg_Used (Reg) then - Gen_Push_Pop_Reg (Opc_Push_Reg, Reg, Sz_Ptr); - end if; - end Push_Reg_If_Used; + Gen_Push_Pop_Reg (Opc_Push_Reg, Reg, Sz_Ptr); + end Push_Reg; - procedure Pop_Reg_If_Used (Reg : Regs_R64) - is - use Ortho_Code.X86.Insns; + procedure Pop_Reg (Reg : Regs_R64) is begin - if Reg_Used (Reg) then - Gen_Push_Pop_Reg (Opc_Pop_Reg, Reg, Sz_Ptr); - end if; - end Pop_Reg_If_Used; + Gen_Push_Pop_Reg (Opc_Pop_Reg, Reg, Sz_Ptr); + end Pop_Reg; procedure Emit_Prologue (Subprg : Subprogram_Data_Acc) is @@ -2868,6 +2864,7 @@ package body Ortho_Code.X86.Emits is Set_Current_Section (Sect_Text); Gen_Pow_Align (2); + -- Set symbol. Subprg_Decl := Subprg.D_Decl; Sym := Get_Decl_Symbol (Subprg_Decl); case Get_Decl_Storage (Subprg_Decl) is @@ -2883,8 +2880,8 @@ package body Ortho_Code.X86.Emits is -- Return address and saved frame pointer are preserved. Saved_Regs_Size := 2; - for I in Preserved_Regs'Range loop - if Reg_Used (Preserved_Regs (I)) then + for R in Preserved_Regs'Range loop + if Preserved_Regs (R) and Reg_Used (R) then Saved_Regs_Size := Saved_Regs_Size + 1; end if; end loop; @@ -2895,6 +2892,8 @@ package body Ortho_Code.X86.Emits is end if; -- Compute frame size. + -- Saved_Regs_Size must be added and substracted as the stack boundary + -- can be larger than a reg size. Frame_Size := Unsigned_32 (Subprg.Stack_Max) + Saved_Regs_Size; -- Align. Frame_Size := (Frame_Size + X86.Flags.Stack_Boundary - 1) @@ -2904,7 +2903,7 @@ package body Ortho_Code.X86.Emits is -- Emit prolog. -- push %ebp / push %rbp - Gen_Push_Pop_Reg (Opc_Push_Reg, R_Bp, Sz_Ptr); + Push_Reg (R_Bp); -- movl %esp, %ebp / movl %rsp, %rbp Start_Insn; Gen_Rex (16#48#); @@ -2912,7 +2911,7 @@ package body Ortho_Code.X86.Emits is Gen_8 (2#11_100_101#); End_Insn; - -- Save int registers. + -- Save int arguments (only on x86-64). Has_Fp_Inter := False; if Flags.M64 then declare @@ -2923,9 +2922,13 @@ package body Ortho_Code.X86.Emits is while Inter /= O_Dnode_Null loop R := Get_Decl_Reg (Inter); if R in Regs_R64 then - Gen_Push_Pop_Reg (Opc_Push_Reg, R, Sz_Ptr); + Push_Reg (R); + -- Space for arguments was already counted in frame size. + -- As the space is allocated by the push, don't allocate it + -- later. Frame_Size := Frame_Size - 8; elsif R in Regs_Xmm then + -- Need to save Xmm registers, but later. Has_Fp_Inter := True; else pragma Assert (R = R_None); @@ -2956,6 +2959,7 @@ package body Ortho_Code.X86.Emits is end if; end if; + -- Save XMM arguments. if Flags.M64 and Has_Fp_Inter then declare Inter : O_Dnode; @@ -2971,6 +2975,7 @@ package body Ortho_Code.X86.Emits is Gen_SSE_Opc (Opc_Movsd_M64_Xmm); Gen_Mod_Rm_Reg; End_Insn; + -- No need to adjust frame_size, it was already allocated. end if; Inter := Get_Interface_Chain (Inter); end loop; @@ -2981,9 +2986,11 @@ package body Ortho_Code.X86.Emits is Gen_Call (Mcount_Symbol); end if; - -- Save registers. - for I in Preserved_Regs'Range loop - Push_Reg_If_Used (Preserved_Regs (I)); + -- Save preserved registers that are used in the function. + for R in Preserved_Regs'Range loop + if Preserved_Regs (R) and Reg_Used (R) then + Push_Reg (R); + end if; end loop; end Emit_Prologue; @@ -2992,12 +2999,15 @@ package body Ortho_Code.X86.Emits is use Ortho_Code.Decls; use Ortho_Code.Types; use Ortho_Code.Flags; + use Ortho_Code.X86.Insns; Decl : O_Dnode; Mode : Mode_Type; begin -- Restore registers. - for I in reverse Preserved_Regs'Range loop - Pop_Reg_If_Used (Preserved_Regs (I)); + for R in reverse Preserved_Regs'Range loop + if Preserved_Regs (R) and Reg_Used (R) then + Pop_Reg (R); + end if; end loop; Decl := Subprg.D_Decl; diff --git a/src/ortho/mcode/ortho_code-x86-insns.adb b/src/ortho/mcode/ortho_code-x86-insns.adb index 099f73e2a..acdcc7746 100644 --- a/src/ortho/mcode/ortho_code-x86-insns.adb +++ b/src/ortho/mcode/ortho_code-x86-insns.adb @@ -1051,15 +1051,35 @@ package body Ortho_Code.X86.Insns is end loop; -- Mark caller saved registers as clobbered. - for R in R_Ax .. R_Dx loop - Clobber_Gp (R); - end loop; - for R in R_Si .. R_R11 loop - Clobber_Gp (R); - end loop; - for R in Regs_Xmm loop - Clobber_Xmm (R); - end loop; + if Flags.Win64 then + -- R12-R15, RSI, RDI, RBX, RBP are preserved by callee. + for R in Preserved_Regs_Win64'Range loop + if not Preserved_Regs_Win64 (R) then + Clobber_Gp (R); + end if; + end loop; + else + -- RBX, R12-R15 are callee-saved (preserved) + for R in Preserved_Regs_Lin64'Range loop + if not Preserved_Regs_Lin64 (R) then + Clobber_Gp (R); + end if; + end loop; + end if; + + if Flags.Win64 then + -- Xmm6 - xmm15 are preserved. + for R in Preserved_Xmm_Win64'Range loop + if not Preserved_Xmm_Win64 (R) then + Clobber_Xmm (R); + end if; + end loop; + else + -- All Xmm registers are for arguments or volatile. + for R in Regs_Xmm loop + Clobber_Xmm (R); + end loop; + end if; end Clobber_Caller_Saved_Registers_64; -- Insert an argument for an intrinsic call. diff --git a/src/ortho/mcode/ortho_code-x86.ads b/src/ortho/mcode/ortho_code-x86.ads index bff3b4b32..27473953b 100644 --- a/src/ortho/mcode/ortho_code-x86.ads +++ b/src/ortho/mcode/ortho_code-x86.ads @@ -167,9 +167,23 @@ package Ortho_Code.X86 is type O_Reg_Array is array (Natural range <>) of O_Reg; + type O_Reg_Bitmap is array (O_Reg range <>) of Boolean; + pragma Pack (O_Reg_Bitmap); + + subtype Regs_R32_Bitmap is O_Reg_Bitmap (Regs_R32); + subtype Regs_R64_Bitmap is O_Reg_Bitmap (Regs_R64); + subtype Regs_Xmm64_Bitmap is O_Reg_Bitmap (Regs_X86_64_Xmm); + -- Registers preserved accross calls. - Preserved_Regs_32 : constant O_Reg_Array := - (R_Di, R_Si, R_Bx); - Preserved_Regs_64 : constant O_Reg_Array := - (R_Bx, R_R12, R_R13, R_R14, R_R15); + Preserved_Regs_32 : constant Regs_R32_Bitmap := + (R_Di | R_Si | R_Bx => True, others => False); + Preserved_Regs_Lin64 : constant Regs_R64_Bitmap := + (R_Bx | R_R12 | R_R13 | R_R14 | R_R15 => True, others => False); + Preserved_Regs_Win64 : constant Regs_R64_Bitmap := + (R_Di | R_Si | R_Bx | R_R12 | R_R13 | R_R14 | R_R15 => True, + others => False); + Preserved_Xmm_Win64 : constant Regs_Xmm64_Bitmap := + (R_Xmm6 | R_Xmm7 | R_Xmm8 | R_Xmm9 | R_Xmm1 | R_Xmm11 + | R_Xmm12 | R_Xmm13 | R_Xmm14 | R_Xmm15 => True, + others => False); end Ortho_Code.X86; -- cgit v1.2.3