aboutsummaryrefslogtreecommitdiffstats
path: root/src/ortho
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2017-06-28 07:52:12 +0200
committerTristan Gingold <tgingold@free.fr>2017-06-28 07:52:12 +0200
commit03634c4038ebca7a43d385aea66a09d73504c769 (patch)
treec843127e4194bfb7699fbfe1903f430ccb803674 /src/ortho
parentb7d2a39f80e4dc06958b8e399a879b163e4eb499 (diff)
downloadghdl-03634c4038ebca7a43d385aea66a09d73504c769.tar.gz
ghdl-03634c4038ebca7a43d385aea66a09d73504c769.tar.bz2
ghdl-03634c4038ebca7a43d385aea66a09d73504c769.zip
ortho/mcode: preliminary work to support win64.
Diffstat (limited to 'src/ortho')
-rw-r--r--src/ortho/mcode/ortho_code-x86-emits.adb64
-rw-r--r--src/ortho/mcode/ortho_code-x86-insns.adb38
-rw-r--r--src/ortho/mcode/ortho_code-x86.ads22
3 files changed, 84 insertions, 40 deletions
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;