aboutsummaryrefslogtreecommitdiffstats
path: root/src/ortho
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2022-04-01 07:31:52 +0200
committerTristan Gingold <tgingold@free.fr>2022-04-01 07:31:52 +0200
commitab2e2eaa2bd8c96b35ae9866b46627fa045cc3f6 (patch)
tree828edd3fb8429baad7fa420eee95018e04007989 /src/ortho
parent6cb10e4d80e36697fea3517651915a7a8a0bc322 (diff)
downloadghdl-ab2e2eaa2bd8c96b35ae9866b46627fa045cc3f6.tar.gz
ghdl-ab2e2eaa2bd8c96b35ae9866b46627fa045cc3f6.tar.bz2
ghdl-ab2e2eaa2bd8c96b35ae9866b46627fa045cc3f6.zip
mcode: improve support of Win64 (prolog)
Diffstat (limited to 'src/ortho')
-rw-r--r--src/ortho/mcode/ortho_code-x86-abi.adb13
-rw-r--r--src/ortho/mcode/ortho_code-x86-emits.adb46
-rw-r--r--src/ortho/mcode/ortho_code-x86-insns.adb11
3 files changed, 41 insertions, 29 deletions
diff --git a/src/ortho/mcode/ortho_code-x86-abi.adb b/src/ortho/mcode/ortho_code-x86-abi.adb
index 69eb8d26e..fa5193982 100644
--- a/src/ortho/mcode/ortho_code-x86-abi.adb
+++ b/src/ortho/mcode/ortho_code-x86-abi.adb
@@ -40,6 +40,10 @@ package body Ortho_Code.X86.Abi is
pragma Unreferenced (Subprg);
begin
Abi := (Offset => Subprg_Stack_Init, Inum => 0, Fnum => 0);
+ if Flags.Win64 then
+ -- On Win64, 32B are always reserved for home registers.
+ Abi.Offset := Abi.Offset + 32;
+ end if;
end Start_Subprogram;
type Regs_List is array (Boolean range <>, Natural range <>) of O_Reg;
@@ -90,8 +94,13 @@ package body Ortho_Code.X86.Abi is
Size := (Size + 3) and not 3;
end if;
Set_Decl_Reg (Inter, Reg);
- Set_Local_Offset (Inter, Abi.Offset);
- Abi.Offset := Abi.Offset + Int32 (Size);
+ if Flags.Win64 and Reg in Regs_R64 then
+ -- Use the normal home location (first reg at offset 8).
+ Set_Local_Offset (Inter, Int32 (8 * Abi.Inum));
+ else
+ Set_Local_Offset (Inter, Abi.Offset);
+ Abi.Offset := Abi.Offset + Int32 (Size);
+ end if;
end New_Interface;
procedure Finish_Subprogram (Subprg : O_Dnode; Abi : in out O_Abi_Subprg)
diff --git a/src/ortho/mcode/ortho_code-x86-emits.adb b/src/ortho/mcode/ortho_code-x86-emits.adb
index 70b1fb584..2a86c9a48 100644
--- a/src/ortho/mcode/ortho_code-x86-emits.adb
+++ b/src/ortho/mcode/ortho_code-x86-emits.adb
@@ -1243,6 +1243,24 @@ package body Ortho_Code.X86.Emits is
End_Insn;
end Emit_Addl_Sp_Imm;
+ procedure Gen_Sub_Sp_Imm (Imm : Int32) is
+ begin
+ Start_Insn;
+ Init_Modrm_Reg (R_Sp, Sz_Ptr);
+ Gen_Insn_Grp1 (Opc2_Grp1_Sub, Imm);
+ End_Insn;
+ end Gen_Sub_Sp_Imm;
+
+ procedure Gen_Sub_Sp_Reg (Reg : O_Reg) is
+ begin
+ -- subl esp, reg
+ Start_Insn;
+ Gen_Rex_B (Reg, Sz_Ptr);
+ Gen_8 (Opc_Subl_Reg_Rm);
+ Gen_8 (2#11_100_000# + To_Reg32 (Reg));
+ End_Insn;
+ end Gen_Sub_Sp_Reg;
+
procedure Emit_Push_Fp (Op : O_Enode; Mode : Mode_Fp)
is
Reg : constant O_Reg := Get_Expr_Reg (Op);
@@ -1648,12 +1666,7 @@ package body Ortho_Code.X86.Emits is
Gen_Call (Chkstk_Symbol);
end if;
if (not X86.Flags.Flag_Alloca_Call) or X86.Flags.Win64 then
- -- subl esp, reg
- Start_Insn;
- Gen_Rex_B (Reg, Sz_Ptr);
- Gen_8 (Opc_Subl_Reg_Rm);
- Gen_8 (2#11_100_000# + To_Reg32 (Reg));
- End_Insn;
+ Gen_Sub_Sp_Reg (Reg);
end if;
-- movl reg, esp
Start_Insn;
@@ -2870,14 +2883,6 @@ package body Ortho_Code.X86.Emits is
Gen_Push_Pop_Reg (Opc_Pop_Reg, Reg, Sz_Ptr);
end Pop_Reg;
- procedure Gen_Sub_Sp (Imm : Int32) is
- begin
- Start_Insn;
- Init_Modrm_Reg (R_Sp, Sz_Ptr);
- Gen_Insn_Grp1 (Opc2_Grp1_Sub, Imm);
- End_Insn;
- end Gen_Sub_Sp;
-
procedure Emit_Prologue (Subprg : Subprogram_Data_Acc)
is
use Ortho_Code.Decls;
@@ -2972,12 +2977,7 @@ package body Ortho_Code.X86.Emits is
-- subl XXX, %esp / subq XXX, %rsp
if Frame_Size /= 0 then
- if not X86.Flags.Flag_Alloca_Call
- or else Frame_Size <= 4096
- then
- Gen_Sub_Sp (Int32 (Frame_Size));
- else
- pragma Assert (not Flags.M64);
+ if X86.Flags.Flag_Alloca_Call and then Frame_Size >= 4096 then
-- mov stack_size,%eax
Start_Insn;
Gen_8 (Opc_Movl_Imm_Reg + To_Reg32 (R_Ax));
@@ -2985,6 +2985,12 @@ package body Ortho_Code.X86.Emits is
End_Insn;
Gen_Call (Chkstk_Symbol);
+
+ if Flags.Win64 then
+ Gen_Sub_Sp_Reg (R_Ax);
+ end if;
+ else
+ Gen_Sub_Sp_Imm (Int32 (Frame_Size));
end if;
end if;
diff --git a/src/ortho/mcode/ortho_code-x86-insns.adb b/src/ortho/mcode/ortho_code-x86-insns.adb
index 0264e952a..9d990c465 100644
--- a/src/ortho/mcode/ortho_code-x86-insns.adb
+++ b/src/ortho/mcode/ortho_code-x86-insns.adb
@@ -1231,7 +1231,6 @@ package body Ortho_Code.X86.Insns is
use Interfaces;
Subprg : constant O_Dnode := Get_Call_Subprg (Stmt);
Push_Size : constant Uns32 := Uns32 (Get_Subprg_Stack (Subprg));
- Push_Home : Uns32;
Reg_Res : O_Reg;
Pad : Uns32;
Res_Stmt : O_Enode;
@@ -1262,10 +1261,8 @@ package body Ortho_Code.X86.Insns is
if Flags.M64 and Flags.Win64 then
-- Need to reserve 4*8 bytes to home registers
- Push_Home := 4*8;
- Gen_Stack_Adjust (Int32 (Push_Home));
- else
- Push_Home := 0;
+ Gen_Stack_Adjust (4*8);
+ Push_Offset := Push_Offset + 32;
end if;
-- Add the call.
@@ -1274,8 +1271,8 @@ package body Ortho_Code.X86.Insns is
Link_Stmt (Stmt);
Res_Stmt := Stmt;
- if Push_Size + Push_Home + Pad /= 0 then
- Gen_Stack_Adjust (-Int32 (Push_Size + Push_Home + Pad));
+ if Push_Size + Pad /= 0 then
+ Gen_Stack_Adjust (-Int32 (Push_Size + Pad));
-- The stack has been restored (just after the call).
Push_Offset := Push_Offset - (Push_Size + Pad);