aboutsummaryrefslogtreecommitdiffstats
path: root/src/ortho
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2015-11-11 04:40:07 +0100
committerTristan Gingold <tgingold@free.fr>2015-11-11 04:40:07 +0100
commit15baf16d632f9425e8a955e0344a8376409db814 (patch)
treec0366d94605524c6a5b69731e374e1c8ce9b5d3d /src/ortho
parent8b20df13007f67f5c25a9801e917ae4feea0826b (diff)
downloadghdl-15baf16d632f9425e8a955e0344a8376409db814.tar.gz
ghdl-15baf16d632f9425e8a955e0344a8376409db814.tar.bz2
ghdl-15baf16d632f9425e8a955e0344a8376409db814.zip
mcode x86: wip: sse support.
Diffstat (limited to 'src/ortho')
-rw-r--r--src/ortho/mcode/ortho_code-exprs.adb5
-rw-r--r--src/ortho/mcode/ortho_code-exprs.ads5
-rw-r--r--src/ortho/mcode/ortho_code-x86-abi.adb8
-rw-r--r--src/ortho/mcode/ortho_code-x86-abi.ads12
-rw-r--r--src/ortho/mcode/ortho_code-x86-emits.adb401
-rw-r--r--src/ortho/mcode/ortho_code-x86-emits.ads2
-rw-r--r--src/ortho/mcode/ortho_code-x86-insns.adb252
-rw-r--r--src/ortho/mcode/ortho_code-x86-insns.ads6
-rw-r--r--src/ortho/mcode/ortho_code-x86.adb38
-rw-r--r--src/ortho/mcode/ortho_code-x86.ads5
10 files changed, 420 insertions, 314 deletions
diff --git a/src/ortho/mcode/ortho_code-exprs.adb b/src/ortho/mcode/ortho_code-exprs.adb
index 7d840cb3c..a45c9f802 100644
--- a/src/ortho/mcode/ortho_code-exprs.adb
+++ b/src/ortho/mcode/ortho_code-exprs.adb
@@ -543,7 +543,8 @@ package body Ortho_Code.Exprs is
D_Body => D_Body,
Exit_Label => O_Enode_Null,
Last_Stmt => O_Enode_Null,
- Stack_Max => 0);
+ Stack_Max => 0,
+ Target => (others => <>));
if not Flag_Debug_Hli then
Data.Exit_Label := New_Label;
@@ -636,7 +637,7 @@ package body Ortho_Code.Exprs is
Disp_Subprg_Body (1, Cur_Subprg.E_Entry);
end if;
if not Ortho_Code.Debug.Flag_Debug_Dump then
- Abi.Finish_Body (Cur_Subprg);
+ Abi.Finish_Body;
end if;
end if;
diff --git a/src/ortho/mcode/ortho_code-exprs.ads b/src/ortho/mcode/ortho_code-exprs.ads
index 9bd4596d7..f8ee88a8e 100644
--- a/src/ortho/mcode/ortho_code-exprs.ads
+++ b/src/ortho/mcode/ortho_code-exprs.ads
@@ -15,6 +15,8 @@
-- along with GCC; see the file COPYING. If not, write to the Free
-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-- 02111-1307, USA.
+with Ortho_Code.Abi;
+
package Ortho_Code.Exprs is
type OE_Kind is
(
@@ -254,6 +256,9 @@ package Ortho_Code.Exprs is
-- Static maximum stack use.
Stack_Max : Uns32;
+
+ -- Target specific data.
+ Target : Abi.Target_Subprg;
end record;
-- Data for the current subprogram.
diff --git a/src/ortho/mcode/ortho_code-x86-abi.adb b/src/ortho/mcode/ortho_code-x86-abi.adb
index 38cfc92d1..8af6a57aa 100644
--- a/src/ortho/mcode/ortho_code-x86-abi.adb
+++ b/src/ortho/mcode/ortho_code-x86-abi.adb
@@ -92,6 +92,7 @@ package body Ortho_Code.X86.Abi is
procedure Finish_Body (Subprg : Subprogram_Data_Acc)
is
+ pragma Assert (Subprg = Cur_Subprg);
use Ortho_Code.Flags;
Child : Subprogram_Data_Acc;
@@ -125,9 +126,11 @@ package body Ortho_Code.X86.Abi is
-- Recurse on nested subprograms.
Child := Subprg.First_Child;
while Child /= null loop
+ Cur_Subprg := Child;
Finish_Body (Child);
Child := Child.Brother;
end loop;
+ Cur_Subprg := Subprg;
if Get_Decl_Depth (Subprg.D_Decl) = O_Toplevel then
if Flag_Debug = Debug_Dwarf then
@@ -146,6 +149,11 @@ package body Ortho_Code.X86.Abi is
end if;
end Finish_Body;
+ procedure Finish_Body is
+ begin
+ Finish_Body (Cur_Subprg);
+ end Finish_Body;
+
procedure Expand_Const_Decl (Decl : O_Dnode) is
begin
Emits.Emit_Const_Decl (Decl);
diff --git a/src/ortho/mcode/ortho_code-x86-abi.ads b/src/ortho/mcode/ortho_code-x86-abi.ads
index 97393cbe1..c7dc49cc9 100644
--- a/src/ortho/mcode/ortho_code-x86-abi.ads
+++ b/src/ortho/mcode/ortho_code-x86-abi.ads
@@ -40,7 +40,7 @@ package Ortho_Code.X86.Abi is
-- If True, use SSE/SSE2 instructions instead of FPU one. The code is
-- still compliant with the ABI (ie FP values are returned in st0).
-- TODO: this is still work in progress.
- Flag_Sse2 : Boolean := False;
+ Flag_Sse2 : constant Boolean := False;
-- Procedures to layout a subprogram declaration.
procedure Start_Subprogram (Subprg : O_Dnode; Abi : out O_Abi_Subprg);
@@ -49,8 +49,8 @@ package Ortho_Code.X86.Abi is
-- Only called for top-level subprograms.
procedure Start_Body (Subprg : O_Dnode);
- -- Finish compilation of a body.
- procedure Finish_Body (Subprg : Subprogram_Data_Acc);
+ -- Finish compilation of a body (body is Cur_Subprg).
+ procedure Finish_Body;
procedure Expand_Const_Decl (Decl : O_Dnode);
procedure Expand_Var_Decl (Decl : O_Dnode);
@@ -71,7 +71,13 @@ package Ortho_Code.X86.Abi is
-- Link in memory intrinsics symbols.
procedure Link_Intrinsics;
+
+ -- Target specific data for subprograms.
+ type Target_Subprg is record
+ Fp_Slot : Uns32 := 0;
+ end record;
private
+ -- Target specific data for O_Inter_List.
type O_Abi_Subprg is record
-- For x86: offset of the next argument.
Offset : Int32 := 0;
diff --git a/src/ortho/mcode/ortho_code-x86-emits.adb b/src/ortho/mcode/ortho_code-x86-emits.adb
index 4e374e40e..6aebd67c6 100644
--- a/src/ortho/mcode/ortho_code-x86-emits.adb
+++ b/src/ortho/mcode/ortho_code-x86-emits.adb
@@ -61,6 +61,7 @@ package body Ortho_Code.X86.Emits is
Opc_Mov_Rm_Imm : constant := 16#c6#; -- Eb,Ib or Ev,Iz (grp11, opc2=0)
Opc_Mov_Rm_Reg : constant := 16#88#; -- Store: Eb,Gb or Ev,Gv
Opc_Mov_Reg_Rm : constant := 16#8a#; -- Load: Gb,Eb or Gv,Ev
+ Opc_Movl_Reg_Rm : constant := 16#8b#; -- Load: Gv,Ev
-- Opc_Grp1_Rm_Imm : constant := 16#80#;
Opc_Grp1b_Rm_Imm8 : constant := 16#80#;
Opc_Grp1v_Rm_Imm32 : constant := 16#81#;
@@ -88,14 +89,16 @@ package body Ortho_Code.X86.Emits is
Opc_Pop_Reg : constant := 16#58#; -- opc[2:0] is reg.
Opc_Grp5 : constant := 16#ff#;
Opc2_Grp5_Push_Rm : constant := 2#110_000#;
- Opc_Grp1a : constant := 16#8f#;
- Opc2_Grp1a_Pop_Rm : constant := 2#000_000#;
+ -- Opc_Grp1a : constant := 16#8f#;
+ -- Opc2_Grp1a_Pop_Rm : constant := 2#000_000#;
Opc_Jcc : constant := 16#70#;
Opc_0f : constant := 16#0f#;
Opc2_0f_Jcc : constant := 16#80#;
Opc2_0f_Setcc : constant := 16#90#;
Opc2_0f_Movzx : constant := 16#b6#;
Opc2_0f_Imul : constant := 16#af#;
+ Opc2_0f_Andnp : constant := 16#55#;
+ Opc2_0f_Xorp : constant := 16#57#;
Opc_Call : constant := 16#e8#;
Opc_Jmp_Long : constant := 16#e9#;
Opc_Jmp_Short : constant := 16#eb#;
@@ -388,7 +391,20 @@ package body Ortho_Code.X86.Emits is
Rm_Sz := Sz;
end Init_Modrm_Reg;
- procedure Init_Rm_Mem (N : O_Enode; Sz : Insn_Size)
+ -- Note: SZ is not relevant.
+ procedure Init_Modrm_Sym (Sym : Symbol; Sz : Insn_Size) is
+ begin
+ Rm_Base := R_Nil;
+ SIB_Index := R_Nil;
+ SIB_Scale := 0;
+ Rm_Sym := Sym;
+ Rm_Offset := 0;
+
+ Rm_Reg := R_Nil;
+ Rm_Sz := Sz;
+ end Init_Modrm_Sym;
+
+ procedure Init_Modrm_Mem (N : O_Enode; Sz : Insn_Size)
is
Reg : constant O_Reg := Get_Expr_Reg (N);
begin
@@ -419,22 +435,42 @@ package body Ortho_Code.X86.Emits is
Rm_Base := R_Bp;
Rm_Offset := Rm_Offset + Get_Spill_Info (N);
when others =>
- Error_Emit ("init_rm_mem: unhandled reg", N);
+ Error_Emit ("init_modrm_mem: unhandled reg", N);
end case;
- end Init_Rm_Mem;
+ end Init_Modrm_Mem;
procedure Init_Rm_Expr (N : O_Enode; Sz : Insn_Size)
is
Reg : constant O_Reg := Get_Expr_Reg (N);
begin
- if Reg in Regs_R32 or Reg in Regs_R64 then
- -- Destination is a register.
- Init_Modrm_Reg (Reg, Sz);
+ case Reg is
+ when Regs_R32
+ | Regs_R64
+ | Regs_Xmm =>
+ -- Destination is a register.
+ Init_Modrm_Reg (Reg, Sz);
+ when others =>
+ -- Destination is an effective address.
+ Init_Modrm_Mem (N, Sz);
+ end case;
+ end Init_Rm_Expr;
+
+ procedure Init_Modrm_Offset (Base : O_Reg; Off : Int32; Sz : Insn_Size) is
+ begin
+ SIB_Index := R_Nil;
+ SIB_Scale := 0;
+ Rm_Reg := R_Nil;
+ Rm_Sym := Null_Symbol;
+ Rm_Sz := Sz;
+
+ Rm_Base := Base;
+
+ if Sz = Sz_32h then
+ Rm_Offset := Off + 4;
else
- -- Destination is an effective address.
- Init_Rm_Mem (N, Sz);
+ Rm_Offset := Off;
end if;
- end Init_Rm_Expr;
+ end Init_Modrm_Offset;
-- Generate an R/M (+ SIB) byte.
-- R is added to the R/M byte.
@@ -475,7 +511,11 @@ package body Ortho_Code.X86.Emits is
pragma Assert (Rm_Base = R_Nil);
pragma Assert (Rm_Sym = Null_Symbol);
pragma Assert (Rm_Offset = 0);
- Gen_B8 (2#11_000_000# + R + To_Reg32 (Rm_Reg, Rm_Sz));
+ if Rm_Reg in Regs_Xmm then
+ Gen_B8 (2#11_000_000# + R + To_Reg_Xmm (Rm_Reg));
+ else
+ Gen_B8 (2#11_000_000# + R + To_Reg32 (Rm_Reg, Rm_Sz));
+ end if;
return;
end if;
@@ -523,7 +563,7 @@ package body Ortho_Code.X86.Emits is
Gen_B8 (2#11_000_000# + R + To_Reg32 (Reg, Sz));
else
-- Destination is an effective address.
- Init_Rm_Mem (N, Sz);
+ Init_Modrm_Mem (N, Sz);
Gen_Mod_Rm (R);
end if;
end Gen_Rm;
@@ -667,9 +707,9 @@ package body Ortho_Code.X86.Emits is
End_Insn;
end Emit_Load_Imm;
- function Mode_Fp_To_Mf (Sz : Mode_Fp) return Byte is
+ function Mode_Fp_To_Mf (Mode : Mode_Fp) return Byte is
begin
- case Sz is
+ case Mode is
when Mode_F32 =>
return 2#00_0#;
when Mode_F64 =>
@@ -714,9 +754,9 @@ package body Ortho_Code.X86.Emits is
Xmm_Sign32_Sym : Symbol := Null_Symbol;
Xmm_Sign64_Sym : Symbol := Null_Symbol;
- function Get_Xmm_Sign_Constant (Sz : Mode_Fp) return Symbol is
+ function Get_Xmm_Sign_Constant (Mode : Mode_Fp) return Symbol is
begin
- case Sz is
+ case Mode is
when Mode_F32 =>
if Xmm_Sign32_Sym = Null_Symbol then
Xmm_Sign32_Sym := Gen_Constant_32 (16#8000_0000#);
@@ -730,13 +770,37 @@ package body Ortho_Code.X86.Emits is
end case;
end Get_Xmm_Sign_Constant;
- procedure Emit_Load_Fp (Stmt : O_Enode; Sz : Mode_Fp)
+ procedure Gen_SSE_Rep_Opc (Sz : Mode_Fp; Opc : Byte) is
+ begin
+ case Sz is
+ when Mode_F32 =>
+ Gen_B8 (16#f3#);
+ when Mode_F64 =>
+ Gen_B8 (16#f2#);
+ end case;
+ Gen_B8 (16#0f#);
+ Gen_B8 (Opc);
+ end Gen_SSE_Rep_Opc;
+
+ procedure Gen_SSE_D16_Opc (Sz : Mode_Fp; Opc : Byte) is
+ begin
+ case Sz is
+ when Mode_F32 =>
+ null;
+ when Mode_F64 =>
+ Gen_B8 (Opc_Data16);
+ end case;
+ Gen_B8 (16#0f#);
+ Gen_B8 (Opc);
+ end Gen_SSE_D16_Opc;
+
+ procedure Emit_Load_Fp (Stmt : O_Enode; Mode : Mode_Fp)
is
Sym : Symbol;
R : O_Reg;
Lo : constant Unsigned_32 := Unsigned_32 (Get_Expr_Low (Stmt));
begin
- case Sz is
+ case Mode is
when Mode_F32 =>
Sym := Gen_Constant_32 (Lo);
when Mode_F64 =>
@@ -748,20 +812,13 @@ package body Ortho_Code.X86.Emits is
case R is
when R_St0 =>
Start_Insn;
- Gen_B8 (2#11011_001# + Mode_Fp_To_Mf (Sz));
+ Gen_B8 (2#11011_001# + Mode_Fp_To_Mf (Mode));
Gen_B8 (2#00_000_101#);
Gen_X86_32 (Sym, 0);
End_Insn;
when Regs_Xmm =>
Start_Insn;
- case Sz is
- when Mode_F32 =>
- Gen_B8 (16#F3#);
- when Mode_F64 =>
- Gen_B8 (16#F2#);
- end case;
- Gen_B8 (16#0f#);
- Gen_B8 (16#10#);
+ Gen_SSE_Rep_Opc (Mode, 16#10#);
Gen_B8 (2#00_000_101# + To_Reg_Xmm (R) * 2#1_000#);
Gen_X86_32 (Sym, 0);
End_Insn;
@@ -775,33 +832,25 @@ package body Ortho_Code.X86.Emits is
return To_Reg_Xmm (R) * 8;
end Xmm_To_Modrm_Reg;
- procedure Gen_Xmm_Modrm
- (Sz : Mode_Fp; Opc : Byte; Dest : O_Reg; Mem : O_Enode) is
+ procedure Gen_Xmm_Modrm (Mode : Mode_Fp; Opc : Byte; Dest : O_Reg) is
begin
Start_Insn;
- case Sz is
- when Mode_F32 =>
- Gen_B8 (16#f3#);
- when Mode_F64 =>
- Gen_B8 (16#f2#);
- end case;
- Gen_B8 (16#0f#);
- Gen_B8 (Opc);
- Init_Rm_Mem (Mem, Sz_32l);
+ Gen_SSE_Rep_Opc (Mode, Opc);
Gen_Mod_Rm (Xmm_To_Modrm_Reg (Dest));
End_Insn;
end Gen_Xmm_Modrm;
- procedure Emit_Load_Fp_Mem (Stmt : O_Enode; Sz : Mode_Fp)
+ procedure Emit_Load_Fp_Mem (Stmt : O_Enode; Mode : Mode_Fp)
is
Dest : constant O_Reg := Get_Expr_Reg (Stmt);
begin
+ Init_Modrm_Mem (Get_Expr_Operand (Stmt), Sz_32l);
if Dest in Regs_Xmm then
- Gen_Xmm_Modrm (Sz, 16#10#, Dest, Get_Expr_Operand (Stmt));
+ Gen_Xmm_Modrm (Mode, 16#10#, Dest);
else
Start_Insn;
- Gen_B8 (2#11011_001# + Mode_Fp_To_Mf (Sz));
- Init_Rm_Mem (Get_Expr_Operand (Stmt), Sz_32l);
+ Gen_B8 (2#11011_001# + Mode_Fp_To_Mf (Mode));
+ Init_Modrm_Mem (Get_Expr_Operand (Stmt), Sz_32l);
Gen_Mod_Rm (2#000_000#);
End_Insn;
end if;
@@ -809,23 +858,21 @@ package body Ortho_Code.X86.Emits is
procedure Emit_Load_Mem (Stmt : O_Enode; Sz : Insn_Size)
is
- Tr : O_Reg;
- Val : O_Enode;
+ Tr : constant O_Reg := Get_Expr_Reg (Stmt);
+ Val : constant O_Enode := Get_Expr_Operand (Stmt);
begin
- Tr := Get_Expr_Reg (Stmt);
- Val := Get_Expr_Operand (Stmt);
case Tr is
when Regs_R32
| Regs_R64 =>
-- mov REG, OP
+ Init_Modrm_Mem (Val, Sz);
Start_Insn;
Gen_Insn_Sz (Opc_Mov_Reg_Rm, Sz);
- Init_Rm_Mem (Val, Sz);
Gen_Mod_Rm (To_Reg32 (Tr, Sz) * 8);
End_Insn;
when R_Eq =>
-- Cmp OP, 1
- Init_Rm_Mem (Val, Sz);
+ Init_Modrm_Mem (Val, Sz);
Gen_Insn_Grp1 (Opc2_Grp1_Cmp, Sz, 1);
when others =>
Error_Emit ("emit_load_mem", Stmt);
@@ -857,7 +904,7 @@ package body Ortho_Code.X86.Emits is
end case;
Gen_B8 (B + To_Reg32 (Tr, Sz));
else
- Init_Rm_Mem (T, Sz);
+ Init_Modrm_Mem (T, Sz);
Gen_Insn_Sz (Opc_Mov_Rm_Imm, Sz);
Gen_Mod_Rm (16#00#);
end if;
@@ -865,7 +912,7 @@ package body Ortho_Code.X86.Emits is
when Regs_R32
| Regs_R64 =>
Gen_Insn_Sz (Opc_Mov_Rm_Reg, Sz);
- Init_Rm_Mem (T, Sz);
+ Init_Modrm_Mem (T, Sz);
Gen_Mod_Rm (To_Reg32 (Rr, Sz) * 8);
when others =>
Error_Emit ("emit_store", Stmt);
@@ -879,7 +926,7 @@ package body Ortho_Code.X86.Emits is
-- fstp
Start_Insn;
Gen_B8 (2#11011_00_1# + Mode_Fp_To_Mf (Sz));
- Init_Rm_Mem (Get_Assign_Target (Stmt), Sz_32l);
+ Init_Modrm_Mem (Get_Assign_Target (Stmt), Sz_32l);
Gen_Mod_Rm (2#011_000#);
End_Insn;
end Emit_Store_Fp;
@@ -908,22 +955,6 @@ package body Ortho_Code.X86.Emits is
End_Insn;
end Emit_Push_32;
- procedure Emit_Pop_32 (Val : O_Enode; Sz : Insn_Size)
- is
- R : constant O_Reg := Get_Expr_Reg (Val);
- begin
- Start_Insn;
- case R is
- when Regs_R32
- | Regs_R64 =>
- Gen_B8 (Opc_Pop_Reg + To_Reg32 (R, Sz));
- when others =>
- Gen_B8 (Opc_Grp1a);
- Gen_Rm (Opc2_Grp1a_Pop_Rm, Val, Sz);
- end case;
- End_Insn;
- end Emit_Pop_32;
-
procedure Emit_Subl_Sp_Imm (Len : Byte) is
begin
Start_Insn;
@@ -942,25 +973,35 @@ package body Ortho_Code.X86.Emits is
End_Insn;
end Emit_Addl_Sp_Imm;
- procedure Emit_Push_Fp (Op : O_Enode; Sz : Mode_Fp)
+ procedure Emit_Push_Fp (Op : O_Enode; Mode : Mode_Fp)
is
- pragma Unreferenced (Op);
+ Reg : constant O_Reg := Get_Expr_Reg (Op);
Len : Byte;
begin
-- subl esp, val
- case Sz is
+ case Mode is
when Mode_F32 =>
Len := 4;
when Mode_F64 =>
Len := 8;
end case;
Emit_Subl_Sp_Imm (Len);
- -- fstp st, (esp)
- Start_Insn;
- Gen_B8 (2#11011_001# + Mode_Fp_To_Mf (Sz));
- Gen_B8 (2#00_011_100#);
- Gen_B8 (2#00_100_100#);
- End_Insn;
+
+ if Reg = R_St0 then
+ -- fstp st, (esp)
+ Start_Insn;
+ Gen_B8 (2#11011_001# + Mode_Fp_To_Mf (Mode));
+ Gen_B8 (2#00_011_100#); -- Modrm: SIB, no disp
+ Gen_B8 (2#00_100_100#); -- SIB: SS=0, no index, base=esp
+ End_Insn;
+ else
+ pragma Assert (Reg in Regs_Xmm);
+ Start_Insn;
+ Gen_SSE_Rep_Opc (Mode, 16#11#);
+ Gen_B8 (To_Reg_Xmm (Reg) * 8 + 2#00_000_100#); -- Modrm: [--]
+ Gen_B8 (2#00_100_100#); -- SIB: SS=0, no index, base=esp
+ End_Insn;
+ end if;
end Emit_Push_Fp;
function Prepare_Label (Label : O_Enode) return Symbol
@@ -1047,7 +1088,7 @@ package body Ortho_Code.X86.Emits is
End_Insn;
end Gen_Call;
- procedure Emit_Setup_Frame (Stmt : O_Enode)
+ procedure Emit_Stack_Adjust (Stmt : O_Enode)
is
Val : constant Int32 := Get_Stack_Adjust (Stmt);
begin
@@ -1058,15 +1099,32 @@ package body Ortho_Code.X86.Emits is
Init_Modrm_Reg (R_Sp, Sz_32l);
Gen_Insn_Grp1 (Opc2_Grp1_Add, Sz_32l, -Val);
end if;
- end Emit_Setup_Frame;
+ end Emit_Stack_Adjust;
procedure Emit_Call (Stmt : O_Enode)
is
use Ortho_Code.Decls;
Subprg : constant O_Dnode := Get_Call_Subprg (Stmt);
Sym : constant Symbol := Get_Decl_Symbol (Subprg);
+ Mode : constant Mode_Type := Get_Expr_Mode (Stmt);
begin
Gen_Call (Sym);
+
+ if Abi.Flag_Sse2 and then Mode in Mode_Fp then
+ -- Move from St0 to Xmm0.
+ -- fstp slot(%ebp)
+ Init_Modrm_Offset
+ (R_Bp, -Int32 (Cur_Subprg.Target.Fp_Slot), Sz_32l);
+ Start_Insn;
+ Gen_B8 (2#11011_001# + Mode_Fp_To_Mf (Mode));
+ Gen_Mod_Rm (2#00_011_000#);
+ End_Insn;
+ -- movsd slot(%ebp), %xmm0
+ Start_Insn;
+ Gen_SSE_Rep_Opc (Mode, 16#10#);
+ Gen_Mod_Rm (2#00_000_000#);
+ End_Insn;
+ end if;
end Emit_Call;
procedure Emit_Intrinsic (Stmt : O_Enode)
@@ -1116,21 +1174,15 @@ package body Ortho_Code.X86.Emits is
procedure Emit_Spill (Stmt : O_Enode; Sz : Insn_Size)
is
- Reg : O_Reg;
- Expr : O_Enode;
+ Expr : constant O_Enode := Get_Expr_Operand (Stmt);
+ Reg : constant O_Reg := Get_Expr_Reg (Expr);
begin
- Expr := Get_Expr_Operand (Stmt);
- Reg := Get_Expr_Reg (Expr);
- if Reg = R_Spill then
- if Get_Expr_Kind (Expr) = OE_Conv then
- return;
- else
- raise Program_Error;
- end if;
- end if;
+ -- A reload is missing.
+ pragma Assert (Reg /= R_Spill);
+ Init_Modrm_Mem (Stmt, Sz);
Start_Insn;
Gen_Insn_Sz (Opc_Mov_Rm_Reg, Sz);
- Gen_Rm (To_Reg32 (Reg, Sz) * 8, Stmt, Sz);
+ Gen_Mod_Rm (To_Reg32 (Reg, Sz) * 8);
End_Insn;
end Emit_Spill;
@@ -1150,7 +1202,7 @@ package body Ortho_Code.X86.Emits is
-- Hack: change the register to use the real address instead of it.
Set_Expr_Reg (Stmt, R_Mem);
- Init_Rm_Mem (Stmt, Sz_32l);
+ Init_Modrm_Mem (Stmt, Sz_32l);
Start_Insn;
Gen_B8 (Opc_Leal_Reg_Rm);
Gen_Mod_Rm (To_Reg32 (Reg) * 8);
@@ -1378,6 +1430,20 @@ package body Ortho_Code.X86.Emits is
Gen_B8 (2#00_000_100#);
Gen_B8 (2#00_100_100#);
End_Insn;
+ if Reg_Res in Regs_Xmm then
+ -- fstp (%esp)
+ Start_Insn;
+ Gen_B8 (2#11011_00_1# + Mode_Fp_To_Mf (Mode_F64));
+ Gen_B8 (2#00_011_100#);
+ Gen_B8 (2#00_100_100#);
+ End_Insn;
+ -- movsd (%esp), %xmm
+ Start_Insn;
+ Gen_SSE_Rep_Opc (Mode_F64, 16#10#);
+ Gen_B8 (To_Reg_Xmm (Reg_Res) * 8 + 2#00_000_100#);
+ Gen_B8 (2#00_100_100#);
+ End_Insn;
+ end if;
-- addl %esp, 4
Emit_Addl_Sp_Imm (4);
when others =>
@@ -1492,6 +1558,20 @@ package body Ortho_Code.X86.Emits is
Gen_B8 (2#00_101_100#);
Gen_B8 (2#00_100_100#);
End_Insn;
+ if Reg_Res in Regs_Xmm then
+ -- fstp (%esp)
+ Start_Insn;
+ Gen_B8 (2#11011_00_1# + Mode_Fp_To_Mf (Mode_F64));
+ Gen_B8 (2#00_011_100#);
+ Gen_B8 (2#00_100_100#);
+ End_Insn;
+ -- movsd (%esp), %xmm
+ Start_Insn;
+ Gen_SSE_Rep_Opc (Mode_F64, 16#10#);
+ Gen_B8 (To_Reg_Xmm (Reg_Res) * 8 + 2#00_000_100#);
+ Gen_B8 (2#00_100_100#);
+ End_Insn;
+ end if;
-- addl %esp, 8
Emit_Addl_Sp_Imm (8);
when others =>
@@ -1500,30 +1580,44 @@ package body Ortho_Code.X86.Emits is
end Gen_Conv_I64;
-- Convert FP to xxx.
- procedure Gen_Conv_Fp (Stmt : O_Enode) is
+ procedure Gen_Conv_Fp (Stmt : O_Enode)
+ is
+ Reg : constant O_Reg := Get_Expr_Reg (Stmt);
begin
case Get_Expr_Mode (Stmt) is
when Mode_I32 =>
- -- subl %esp, 4
- Emit_Subl_Sp_Imm (4);
- -- fistp (%esp)
+ -- fistpl slot(%ebp)
+ Init_Modrm_Offset
+ (R_Bp, -Int32 (Cur_Subprg.Target.Fp_Slot), Sz_32l);
Start_Insn;
Gen_B8 (2#11011_011#);
- Gen_B8 (2#00_011_100#);
- Gen_B8 (2#00_100_100#);
+ Gen_Mod_Rm (2#00_011_000#);
+ End_Insn;
+ -- movl slot(%ebp), reg
+ -- Keep same modrm parameters.
+ Start_Insn;
+ Gen_B8 (Opc_Movl_Reg_Rm);
+ Gen_Mod_Rm (To_Reg32 (Reg, Sz_32l) * 8);
End_Insn;
- Emit_Pop_32 (Stmt, Sz_32l);
when Mode_I64 =>
- -- subl %esp, 8
- Emit_Subl_Sp_Imm (8);
- -- fistp (%esp)
+ -- fistpq (%esp)
+ Init_Modrm_Offset
+ (R_Bp, -Int32 (Cur_Subprg.Target.Fp_Slot), Sz_32l);
Start_Insn;
Gen_B8 (2#11011_111#);
- Gen_B8 (2#00_111_100#);
- Gen_B8 (2#00_100_100#);
+ Gen_Mod_Rm (2#00_111_000#);
+ End_Insn;
+ -- movl slot(%ebp), reg
+ -- Keep same modrm parameters.
+ Start_Insn;
+ Gen_B8 (Opc_Movl_Reg_Rm);
+ Gen_Mod_Rm (To_Reg32 (Reg, Sz_32l) * 8);
+ End_Insn;
+ Rm_Offset := Rm_Offset + 4;
+ Start_Insn;
+ Gen_B8 (Opc_Movl_Reg_Rm);
+ Gen_Mod_Rm (To_Reg32 (Reg, Sz_32h) * 8);
End_Insn;
- Emit_Pop_32 (Stmt, Sz_32l);
- Emit_Pop_32 (Stmt, Sz_32h);
when others =>
Error_Emit ("gen_conv_fp", Stmt);
end case;
@@ -1591,7 +1685,7 @@ package body Ortho_Code.X86.Emits is
raise Program_Error;
end case;
Gen_B8 (2#11011_000# or B_Size);
- Init_Rm_Mem (Right, Sz_32l);
+ Init_Modrm_Mem (Right, Sz_32l);
Gen_Mod_Rm (B_Mem);
when others =>
raise Program_Error;
@@ -1605,8 +1699,13 @@ package body Ortho_Code.X86.Emits is
Reg : constant O_Reg := Get_Expr_Reg (Stmt);
begin
if Reg in Regs_Xmm then
- Gen_Xmm_Modrm
- (Get_Expr_Mode (Stmt), Xmm_Op, Reg, Get_Expr_Right (Stmt));
+ declare
+ Mode : constant Mode_Type := Get_Expr_Mode (Stmt);
+ Right : constant O_Enode := Get_Expr_Right (Stmt);
+ begin
+ Init_Rm_Expr (Right, Sz_32l);
+ Gen_Xmm_Modrm (Mode, Xmm_Op, Reg);
+ end;
else
Gen_Emit_Fp_Op (Stmt, B_St1, B_Mem);
end if;
@@ -1831,13 +1930,12 @@ package body Ortho_Code.X86.Emits is
| Mode_F64 =>
Reg := Get_Expr_Reg (Stmt);
if Reg in Regs_Xmm then
- declare
- Cst : Symbol;
- begin
- Cst := Get_Xmm_Sign_Constant (Mode);
- pragma Unreferenced (Cst);
- raise Program_Error;
- end;
+ -- Xorp{sd} reg, cst
+ Init_Modrm_Sym (Get_Xmm_Sign_Constant (Mode), Sz_32l);
+ Start_Insn;
+ Gen_SSE_D16_Opc (Mode, Opc2_0f_Xorp);
+ Gen_Mod_Rm (Xmm_To_Modrm_Reg (Reg));
+ End_Insn;
else
-- fchs
Gen_2 (2#11011_001#, 2#1110_0000#);
@@ -1853,8 +1951,18 @@ package body Ortho_Code.X86.Emits is
Emit_Abs (Get_Expr_Operand (Stmt), Mode);
when Mode_F32
| Mode_F64 =>
- -- fabs
- Gen_2 (2#11011_001#, 2#1110_0001#);
+ Reg := Get_Expr_Reg (Stmt);
+ if Reg in Regs_Xmm then
+ -- Andnp{sd} reg, cst
+ Init_Modrm_Sym (Get_Xmm_Sign_Constant (Mode), Sz_32l);
+ Start_Insn;
+ Gen_SSE_D16_Opc (Mode, Opc2_0f_Andnp);
+ Gen_Mod_Rm (Xmm_To_Modrm_Reg (Reg));
+ End_Insn;
+ else
+ -- fabs
+ Gen_2 (2#11011_001#, 2#1110_0001#);
+ end if;
when others =>
Error_Emit ("emit_insn: abs_ov", Stmt);
end case;
@@ -1891,7 +1999,7 @@ package body Ortho_Code.X86.Emits is
Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_32h);
-- Note: this does not clobber a reg due to care in
-- insns.
- Emit_Setcc_Reg (Reg, Ekind_Signed_To_Cc (Kind));
+ Emit_Setcc_Reg (Reg, Insns.Ekind_Signed_To_Cc (Kind));
-- jne
Start_Insn;
Gen_B8 (Opc_Jcc + 2#0101#);
@@ -1899,7 +2007,7 @@ package body Ortho_Code.X86.Emits is
End_Insn;
Pc := Get_Current_Pc;
Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_32l);
- Emit_Setcc_Reg (Reg, Ekind_Unsigned_To_Cc (Kind));
+ Emit_Setcc_Reg (Reg, Insns.Ekind_Unsigned_To_Cc (Kind));
Patch_B8 (Pc - 1, Unsigned_8 (Get_Current_Pc - Pc));
return;
end;
@@ -2039,7 +2147,7 @@ package body Ortho_Code.X86.Emits is
Error_Emit ("emit_insn: oe_arg", Stmt);
end case;
when OE_Stack_Adjust =>
- Emit_Setup_Frame (Stmt);
+ Emit_Stack_Adjust (Stmt);
when OE_Call =>
Emit_Call (Stmt);
when OE_Intrinsic =>
@@ -2047,12 +2155,10 @@ package body Ortho_Code.X86.Emits is
when OE_Move =>
declare
- Operand : O_Enode;
- Op_Reg : O_Reg;
+ Operand : constant O_Enode := Get_Expr_Operand (Stmt);
+ Op_Reg : constant O_Reg := Get_Expr_Reg (Operand);
begin
Reg := Get_Expr_Reg (Stmt);
- Operand := Get_Expr_Operand (Stmt);
- Op_Reg := Get_Expr_Reg (Operand);
case Mode is
when Mode_B2 =>
if Reg in Regs_R32 and then Op_Reg in Regs_Cc then
@@ -2108,16 +2214,25 @@ package body Ortho_Code.X86.Emits is
| Mode_I64 =>
Emit_Spill (Stmt, Sz_32l);
Emit_Spill (Stmt, Sz_32h);
+ when Mode_F32
+ | Mode_F64 =>
+ Reg := Get_Expr_Reg (Stmt);
+ pragma Assert (Reg in Regs_Xmm);
+ -- movsd
+ Init_Modrm_Mem (Stmt, Sz_32l);
+ Start_Insn;
+ Gen_SSE_Rep_Opc (Mode_F64, 16#11#);
+ Gen_Mod_Rm (To_Reg_Xmm (Reg) * 8);
+ End_Insn;
when others =>
Error_Emit ("emit_insn: spill", Stmt);
end case;
when OE_Reload =>
declare
- Expr : O_Enode;
+ Expr : constant O_Enode := Get_Expr_Operand (Stmt);
begin
Reg := Get_Expr_Reg (Stmt);
- Expr := Get_Expr_Operand (Stmt);
case Mode is
when Mode_B2
| Mode_U8
@@ -2131,6 +2246,15 @@ package body Ortho_Code.X86.Emits is
| Mode_I64 =>
Emit_Load (Reg, Expr, Sz_32l);
Emit_Load (Reg, Expr, Sz_32h);
+ when Mode_F32
+ | Mode_F64 =>
+ pragma Assert (Reg in Regs_Xmm);
+ -- movsd
+ Init_Modrm_Mem (Expr, Sz_32l);
+ Start_Insn;
+ Gen_SSE_Rep_Opc (Mode_F64, 16#10#);
+ Gen_Mod_Rm (To_Reg_Xmm (Reg) * 8);
+ End_Insn;
when others =>
Error_Emit ("emit_insn: reload", Stmt);
end case;
@@ -2254,6 +2378,7 @@ package body Ortho_Code.X86.Emits is
use Ortho_Code.Types;
use Ortho_Code.Flags;
Decl : O_Dnode;
+ Mode : Mode_Type;
begin
-- Restore registers.
Pop_Reg_If_Used (R_Bx);
@@ -2262,7 +2387,8 @@ package body Ortho_Code.X86.Emits is
Decl := Subprg.D_Decl;
if Get_Decl_Kind (Decl) = OD_Function then
- case Get_Type_Mode (Get_Decl_Type (Decl)) is
+ Mode := Get_Type_Mode (Get_Decl_Type (Decl));
+ case Mode is
when Mode_U8
| Mode_B2 =>
-- movzx %al,%eax
@@ -2275,10 +2401,24 @@ package body Ortho_Code.X86.Emits is
| Mode_I32
| Mode_U64
| Mode_I64
- | Mode_F32
- | Mode_F64
| Mode_P32 =>
null;
+ when Mode_F32
+ | Mode_F64 =>
+ if Abi.Flag_Sse2 then
+ -- movsd %xmm0, slot(%ebp)
+ Init_Modrm_Offset
+ (R_Bp, -Int32 (Cur_Subprg.Target.Fp_Slot), Sz_32l);
+ Start_Insn;
+ Gen_SSE_Rep_Opc (Mode, 16#11#);
+ Gen_Mod_Rm (2#00_000_000#);
+ End_Insn;
+ -- fldl slot(%ebp)
+ Start_Insn;
+ Gen_B8 (2#11011_001# + Mode_Fp_To_Mf (Mode));
+ Gen_Mod_Rm (2#00_000_000#);
+ End_Insn;
+ end if;
when others =>
raise Program_Error;
end case;
@@ -2295,6 +2435,7 @@ package body Ortho_Code.X86.Emits is
procedure Emit_Subprg (Subprg : Subprogram_Data_Acc)
is
+ pragma Assert (Subprg = Cur_Subprg);
Stmt : O_Enode;
begin
if Debug.Flag_Debug_Code2 then
diff --git a/src/ortho/mcode/ortho_code-x86-emits.ads b/src/ortho/mcode/ortho_code-x86-emits.ads
index 9ddb43ee5..1813f9bd2 100644
--- a/src/ortho/mcode/ortho_code-x86-emits.ads
+++ b/src/ortho/mcode/ortho_code-x86-emits.ads
@@ -16,6 +16,7 @@
-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-- 02111-1307, USA.
with Binary_File; use Binary_File;
+with Ortho_Code.Exprs; use Ortho_Code.Exprs;
package Ortho_Code.X86.Emits is
procedure Init;
@@ -33,4 +34,3 @@ package Ortho_Code.X86.Emits is
Mcount_Symbol : Symbol;
Chkstk_Symbol : Symbol;
end Ortho_Code.X86.Emits;
-
diff --git a/src/ortho/mcode/ortho_code-x86-insns.adb b/src/ortho/mcode/ortho_code-x86-insns.adb
index 56fe9adfe..f2dda8a9f 100644
--- a/src/ortho/mcode/ortho_code-x86-insns.adb
+++ b/src/ortho/mcode/ortho_code-x86-insns.adb
@@ -77,6 +77,9 @@ package body Ortho_Code.X86.Insns is
-- is used to correctly align the stack for nested calls.
Push_Offset : Uns32 := 0;
+ -- If True, allocate 8 bytes on the stack for fp-int/sse conversion.
+ Need_Fp_Conv_Slot : Boolean := False;
+
-- STMT is an OE_END statement.
-- Swap Stack_Offset with Max_Stack of STMT.
procedure Swap_Stack_Offset (Blk : O_Dnode)
@@ -88,16 +91,14 @@ package body Ortho_Code.X86.Insns is
Stack_Offset := Prev_Offset;
end Swap_Stack_Offset;
+ -- Allocate a slot for each local variable.
procedure Expand_Decls (Block : O_Dnode)
is
- Last : O_Dnode;
+ pragma Assert (Get_Decl_Kind (Block) = OD_Block);
+ Last : constant O_Dnode := Get_Block_Last (Block);
Decl : O_Dnode;
Decl_Type : O_Tnode;
begin
- if Get_Decl_Kind (Block) /= OD_Block then
- raise Program_Error;
- end if;
- Last := Get_Block_Last (Block);
Decl := Block + 1;
while Decl <= Last loop
case Get_Decl_Kind (Decl) is
@@ -126,11 +127,46 @@ package body Ortho_Code.X86.Insns is
end loop;
end Expand_Decls;
+ function Ekind_Unsigned_To_Cc (Kind : OE_Kind_Cmp) return O_Reg is
+ begin
+ case Kind is
+ when OE_Eq =>
+ return R_Eq;
+ when OE_Neq =>
+ return R_Ne;
+ when OE_Lt =>
+ return R_Ult;
+ when OE_Le =>
+ return R_Ule;
+ when OE_Gt =>
+ return R_Ugt;
+ when OE_Ge =>
+ return R_Uge;
+ end case;
+ end Ekind_Unsigned_To_Cc;
+
+ function Ekind_Signed_To_Cc (Kind : OE_Kind_Cmp) return O_Reg is
+ begin
+ case Kind is
+ when OE_Eq =>
+ return R_Eq;
+ when OE_Neq =>
+ return R_Ne;
+ when OE_Lt =>
+ return R_Slt;
+ when OE_Le =>
+ return R_Sle;
+ when OE_Gt =>
+ return R_Sgt;
+ when OE_Ge =>
+ return R_Sge;
+ end case;
+ end Ekind_Signed_To_Cc;
+
function Ekind_To_Cc (Stmt : O_Enode; Mode : Mode_Type) return O_Reg
is
- Kind : OE_Kind;
+ Kind : constant OE_Kind := Get_Expr_Kind (Stmt);
begin
- Kind := Get_Expr_Kind (Stmt);
case Mode is
when Mode_U8 .. Mode_U64
| Mode_F32 .. Mode_F64
@@ -176,7 +212,7 @@ package body Ortho_Code.X86.Insns is
end Reverse_Cc;
-- Get the register in which a result of MODE is returned.
- function Get_Call_Register (Mode : Mode_Type) return O_Reg is
+ function Get_Return_Register (Mode : Mode_Type) return O_Reg is
begin
case Mode is
when Mode_U8 .. Mode_U32
@@ -189,9 +225,11 @@ package body Ortho_Code.X86.Insns is
return R_Edx_Eax;
when Mode_F32
| Mode_F64 =>
- if Abi.Flag_Sse2 and True then
- -- Note: this shouldn't be enabled as the svr4 ABI specifies
- -- ST0.
+ if Abi.Flag_Sse2 then
+ -- Strictly speaking, this is not true as ST0 is used on x86.
+ -- The conversion is done by emits (this requires a stack
+ -- slot).
+ Need_Fp_Conv_Slot := True;
return R_Xmm0;
else
return R_St0;
@@ -203,33 +241,7 @@ package body Ortho_Code.X86.Insns is
| Mode_P64 =>
raise Program_Error;
end case;
- end Get_Call_Register;
-
--- function Ensure_Rm (Stmt : O_Enode) return O_Enode
--- is
--- begin
--- case Get_Expr_Reg (Stmt) is
--- when R_Mem
--- | Regs_Any32 =>
--- return Stmt;
--- when others =>
--- raise Program_Error;
--- end case;
--- end Ensure_Rm;
-
--- function Ensure_Ireg (Stmt : O_Enode) return O_Enode
--- is
--- Reg : O_Reg;
--- begin
--- Reg := Get_Expr_Reg (Stmt);
--- case Reg is
--- when Regs_Any32
--- | R_Imm =>
--- return Stmt;
--- when others =>
--- raise Program_Error;
--- end case;
--- end Ensure_Ireg;
+ end Get_Return_Register;
function Insert_Move (Expr : O_Enode; Dest : O_Reg) return O_Enode
is
@@ -242,17 +254,6 @@ package body Ortho_Code.X86.Insns is
return N;
end Insert_Move;
--- function Insert_Spill (Expr : O_Enode) return O_Enode
--- is
--- N : O_Enode;
--- begin
--- N := New_Enode (OE_Spill, Get_Expr_Mode (Expr), O_Tnode_Null,
--- Expr, O_Enode_Null);
--- Set_Expr_Reg (N, R_Spill);
--- Link_Stmt (N);
--- return N;
--- end Insert_Spill;
-
procedure Error_Gen_Insn (Stmt : O_Enode; Reg : O_Reg)
is
use Ada.Text_IO;
@@ -280,7 +281,6 @@ package body Ortho_Code.X86.Insns is
O_Free : constant O_Inum := 0;
O_Iroot : constant O_Inum := 1;
-
Insn_Num : O_Inum;
function Get_Insn_Num return O_Inum is
@@ -424,9 +424,8 @@ package body Ortho_Code.X86.Insns is
-- Allocate a stack slot for spilling.
procedure Alloc_Spill (N : O_Enode)
is
- Mode : Mode_Type;
+ Mode : constant Mode_Type := Get_Expr_Mode (N);
begin
- Mode := Get_Expr_Mode (N);
-- Allocate on the stack.
Stack_Offset := Types.Do_Align (Stack_Offset, Mode);
Stack_Offset := Stack_Offset + Types.Get_Mode_Size (Mode);
@@ -442,12 +441,11 @@ package body Ortho_Code.X86.Insns is
-- ORIG uses a R64 register).
function Insert_Spill (Orig : O_Enode) return O_Reg
is
+ Mode : constant Mode_Type := Get_Expr_Mode (Orig);
N : O_Enode;
- Mode : Mode_Type;
Reg_Orig : O_Reg;
begin
-- Add a spill statement.
- Mode := Get_Expr_Mode (Orig);
N := New_Enode (OE_Spill, Mode, O_Tnode_Null, Orig, O_Enode_Null);
Alloc_Spill (N);
@@ -461,6 +459,9 @@ package body Ortho_Code.X86.Insns is
Set_Stmt_Link (N, Get_Stmt_Link (Orig));
Set_Stmt_Link (Orig, N);
end if;
+
+ -- Mark the target of the original expression as split (so that it is
+ -- marked as to be reloaded), and save the register in the spill insn.
Reg_Orig := Get_Expr_Reg (Orig);
Set_Expr_Reg (N, Reg_Orig);
Set_Expr_Reg (Orig, R_Spill);
@@ -471,19 +472,15 @@ package body Ortho_Code.X86.Insns is
is
Reg_Orig : O_Reg;
begin
- if Regs (Reg).Num = O_Free then
- -- This register was not allocated.
- raise Program_Error;
- end if;
+ -- This register was not allocated.
+ pragma Assert (Regs (Reg).Num /= O_Free);
Reg_Orig := Insert_Spill (Regs (Reg).Stmt);
-- Free the register.
case Reg_Orig is
when Regs_R32 =>
- if Reg_Orig /= Reg then
- raise Program_Error;
- end if;
+ pragma Assert (Reg_Orig = Reg);
Free_R32 (Reg);
when Regs_R64 =>
-- The pair was spilled, so the pair is free.
@@ -523,10 +520,9 @@ package body Ortho_Code.X86.Insns is
procedure Alloc_R64 (Reg : O_Reg; Stmt : O_Enode; Num : O_Inum)
is
- Rh, Rl : O_Reg;
+ Rl : constant O_Reg := Get_R64_Low (Reg);
+ Rh : constant O_Reg := Get_R64_High (Reg);
begin
- Rl := Get_R64_Low (Reg);
- Rh := Get_R64_High (Reg);
if Regs (Rl).Num /= O_Free
or Regs (Rh).Num /= O_Free
then
@@ -538,9 +534,7 @@ package body Ortho_Code.X86.Insns is
procedure Alloc_Cc (Stmt : O_Enode; Num : O_Inum) is
begin
- if Reg_Cc.Num /= O_Free then
- raise Program_Error;
- end if;
+ pragma Assert (Reg_Cc.Num = O_Free);
Reg_Cc := (Num => Num, Stmt => Stmt, Used => True);
end Alloc_Cc;
@@ -548,17 +542,13 @@ package body Ortho_Code.X86.Insns is
is
Reg_Orig : O_Reg;
begin
- if Xmm_Regs (Reg).Num = O_Free then
- -- This register was not allocated.
- raise Program_Error;
- end if;
+ -- This register was not allocated.
+ pragma Assert (Xmm_Regs (Reg).Num /= O_Free);
Reg_Orig := Insert_Spill (Xmm_Regs (Reg).Stmt);
-- Free the register.
- if Reg_Orig /= Reg then
- raise Program_Error;
- end if;
+ pragma Assert (Reg_Orig = Reg);
Free_Xmm (Reg);
end Spill_Xmm;
@@ -576,7 +566,6 @@ package body Ortho_Code.X86.Insns is
Spill_Xmm (Reg);
end if;
end Clobber_Xmm;
- pragma Unreferenced (Clobber_Xmm);
function Alloc_Reg (Reg : O_Reg; Stmt : O_Enode; Num : O_Inum) return O_Reg
is
@@ -674,11 +663,10 @@ package body Ortho_Code.X86.Insns is
function Gen_Reload (Spill : O_Enode; Reg : O_Reg; Num : O_Inum)
return O_Enode
is
+ Mode : constant Mode_Type := Get_Expr_Mode (Spill);
N : O_Enode;
- Mode : Mode_Type;
begin
-- Add a reload node.
- Mode := Get_Expr_Mode (Spill);
N := New_Enode (OE_Reload, Mode, O_Tnode_Null, Spill, O_Enode_Null);
-- Note: this does not use a just-freed register, since
-- this case only occurs at the first call.
@@ -689,10 +677,9 @@ package body Ortho_Code.X86.Insns is
function Reload (Expr : O_Enode; Dest : O_Reg; Num : O_Inum) return O_Enode
is
- Reg : O_Reg;
+ Reg : constant O_Reg := Get_Expr_Reg (Expr);
Spill : O_Enode;
begin
- Reg := Get_Expr_Reg (Expr);
case Reg is
when R_Spill =>
-- Restore the register between the statement and the spill.
@@ -703,6 +690,7 @@ package body Ortho_Code.X86.Insns is
when R_Mem
| R_Irm
| R_Rm =>
+ -- Some instructions can do the reload by themself.
return Spill;
when Regs_R32
| R_Any32
@@ -813,9 +801,8 @@ package body Ortho_Code.X86.Insns is
procedure Free_Insn_Regs (Insn : O_Enode)
is
- R : O_Reg;
+ R : constant O_Reg := Get_Expr_Reg (Insn);
begin
- R := Get_Expr_Reg (Insn);
case R is
when R_Ax
| R_Bx
@@ -893,11 +880,10 @@ package body Ortho_Code.X86.Insns is
function Insert_Intrinsic (Stmt : O_Enode; Reg : O_Reg; Num : O_Inum)
return O_Enode
is
+ Mode : constant Mode_Type := Get_Expr_Mode (Stmt);
N : O_Enode;
Op : Int32;
- Mode : Mode_Type;
begin
- Mode := Get_Expr_Mode (Stmt);
case Get_Expr_Kind (Stmt) is
when OE_Mul_Ov =>
case Mode is
@@ -961,11 +947,13 @@ package body Ortho_Code.X86.Insns is
Pnum : O_Inum)
return O_Enode
is
- Num : O_Inum;
Left : O_Enode;
+ Num : O_Inum;
begin
- Left := Get_Expr_Operand (Stmt);
+ -- Need a temporary to work. Always use FPU.
+ Need_Fp_Conv_Slot := True;
Num := Get_Insn_Num;
+ Left := Get_Expr_Operand (Stmt);
Left := Gen_Insn (Left, R_St0, Num);
Free_Insn_Regs (Left);
Set_Expr_Operand (Stmt, Left);
@@ -984,46 +972,20 @@ package body Ortho_Code.X86.Insns is
end case;
Link_Stmt (Stmt);
return Stmt;
--- declare
--- Spill : O_Enode;
--- begin
--- Num := Get_Insn_Num;
--- Left := Gen_Insn (Left, R_St0, Num);
--- Set_Expr_Operand (Stmt, Left);
--- Set_Expr_Reg (Stmt, R_Spill);
--- Free_Insn_Regs (Left);
--- Link_Stmt (Stmt);
--- Spill := Insert_Spill (Stmt);
--- case Reg is
--- when R_Any32
--- | Regs_R32 =>
--- return Gen_Reload (Spill, Reg, Pnum);
--- when R_Ir =>
--- return Gen_Reload (Spill, R_Any32, Pnum);
--- when R_Rm
--- | R_Irm =>
--- return Spill;
--- when others =>
--- Error_Reg
--- ("gen_insn:oe_conv(fp)", Stmt, Reg);
--- end case;
--- end;
end Gen_Conv_From_Fp_Insn;
function Gen_Call (Stmt : O_Enode; Reg : O_Reg; Pnum : O_Inum)
return O_Enode
is
use Interfaces;
+ Subprg : constant O_Dnode := Get_Call_Subprg (Stmt);
+ Push_Size : constant Uns32 := Uns32 (Get_Subprg_Stack (Subprg));
Left : O_Enode;
Reg_Res : O_Reg;
- Subprg : O_Dnode;
- Push_Size : Uns32;
Pad : Uns32;
Res_Stmt : O_Enode;
begin
-- Emit Setup_Frame (to align stack).
- Subprg := Get_Call_Subprg (Stmt);
- Push_Size := Uns32 (Get_Subprg_Stack (Subprg));
-- Pad the stack if necessary.
Pad := (Push_Size + Push_Offset) and Uns32 (Flags.Stack_Boundary - 1);
if Pad /= 0 then
@@ -1046,8 +1008,14 @@ package body Ortho_Code.X86.Insns is
Clobber_R32 (R_Cx);
-- FIXME: fp regs.
+ if Abi.Flag_Sse2 then
+ for R in Regs_Xmm loop
+ Clobber_Xmm (R);
+ end loop;
+ end if;
+
-- Add the call.
- Reg_Res := Get_Call_Register (Get_Expr_Mode (Stmt));
+ Reg_Res := Get_Return_Register (Get_Expr_Mode (Stmt));
Set_Expr_Reg (Stmt, Reg_Res);
Link_Stmt (Stmt);
Res_Stmt := Stmt;
@@ -1067,13 +1035,15 @@ package body Ortho_Code.X86.Insns is
when R_Any32
| R_Any64
| R_Any8
+ | R_Any_Xmm
| R_Irm
| R_Rm
| R_Ir
| R_Sib
| R_Ax
| R_St0
- | R_Edx_Eax =>
+ | R_Edx_Eax
+ | R_Xmm0 =>
Reg_Res := Alloc_Reg (Reg_Res, Res_Stmt, Pnum);
return Res_Stmt;
when R_Any_Cc =>
@@ -1082,9 +1052,7 @@ package body Ortho_Code.X86.Insns is
Alloc_Cc (Res_Stmt, Pnum);
return Insert_Move (Res_Stmt, R_Ne);
when R_None =>
- if Reg_Res /= R_None then
- raise Program_Error;
- end if;
+ pragma Assert (Reg_Res = R_None);
return Res_Stmt;
when others =>
Error_Gen_Insn (Stmt, Reg);
@@ -1211,6 +1179,7 @@ package body Ortho_Code.X86.Insns is
when OE_Conv_Ptr =>
-- Delete nops.
return Gen_Insn (Get_Expr_Operand (Stmt), Reg, Pnum);
+
when OE_Const =>
case Get_Expr_Mode (Stmt) is
when Mode_U8 .. Mode_U32
@@ -1247,6 +1216,7 @@ package body Ortho_Code.X86.Insns is
when R_Ir
| R_Irm
| R_Rm
+ | R_Any_Xmm
| R_St0 =>
Num := Get_Insn_Num;
if Reg = R_St0 or not Abi.Flag_Sse2 then
@@ -1279,6 +1249,7 @@ package body Ortho_Code.X86.Insns is
raise Program_Error;
end case;
return Stmt;
+
when OE_Alloca =>
-- Roughly speaking, emited code is: (MASK is a constant).
-- VAL := (VAL + MASK) & ~MASK
@@ -1291,6 +1262,7 @@ package body Ortho_Code.X86.Insns is
| R_Any32 =>
Num := Get_Insn_Num;
if X86.Flags.Flag_Alloca_Call then
+ -- The alloca function returns its result in ax.
Reg_L := R_Ax;
else
Reg_L := R_Any32;
@@ -1523,9 +1495,8 @@ package body Ortho_Code.X86.Insns is
Set_Expr_Left (Stmt, Left);
Right := Gen_Insn (Get_Expr_Right (Stmt), R_Any32, Num);
- if Get_Expr_Kind (Right) /= OE_Const then
- raise Program_Error;
- end if;
+ -- Only used to compute memory offset
+ pragma Assert (Get_Expr_Kind (Right) = OE_Const);
Set_Expr_Right (Stmt, Right);
Free_Insn_Regs (Left);
@@ -1628,10 +1599,9 @@ package body Ortho_Code.X86.Insns is
| OE_Mul_Ov
| OE_Div_Ov =>
declare
- Mode : Mode_Type;
+ Mode : constant Mode_Type := Get_Expr_Mode (Stmt);
begin
Num := Get_Insn_Num;
- Mode := Get_Expr_Mode (Stmt);
Left := Get_Expr_Left (Stmt);
Right := Get_Expr_Right (Stmt);
case Mode is
@@ -1677,13 +1647,14 @@ package body Ortho_Code.X86.Insns is
return Insert_Intrinsic (Stmt, R_Edx_Eax, Pnum);
when Mode_F32
| Mode_F64 =>
- Left := Gen_Insn (Left, R_St0, Num);
+ Reg_Res := Get_Reg_Any (Mode);
+ Left := Gen_Insn (Left, Reg_Res, Num);
Right := Gen_Insn (Right, R_Rm, Num);
Set_Expr_Left (Stmt, Left);
Set_Expr_Right (Stmt, Right);
Free_Insn_Regs (Right);
Free_Insn_Regs (Left);
- Set_Expr_Reg (Stmt, Alloc_Reg (R_St0, Stmt, Pnum));
+ Set_Expr_Reg (Stmt, Alloc_Reg (Reg_Res, Stmt, Pnum));
Link_Stmt (Stmt);
return Stmt;
when others =>
@@ -1750,6 +1721,7 @@ package body Ortho_Code.X86.Insns is
-- By default, can work on reg or memory.
Reg_Op := R_Rm;
+ -- Case on target.
case R_Mode is
when Mode_B2 =>
-- To B2
@@ -1884,7 +1856,9 @@ package body Ortho_Code.X86.Insns is
| R_Any64
| R_Any8
| Regs_R64
- | Regs_Fp =>
+ | Regs_Fp
+ | R_Any_Xmm
+ | Regs_Xmm =>
Free_Insn_Regs (Left);
Set_Expr_Reg
(Stmt, Alloc_Reg (Get_Reg_Any (Stmt), Stmt, Pnum));
@@ -1895,9 +1869,7 @@ package body Ortho_Code.X86.Insns is
return Stmt;
end;
when OE_Arg =>
- if Reg /= R_None then
- raise Program_Error;
- end if;
+ pragma Assert (Reg = R_None);
Left := Get_Arg_Link (Stmt);
if Left /= O_Enode_Null then
-- Recurse on next argument, so the first argument is pushed
@@ -1909,7 +1881,11 @@ package body Ortho_Code.X86.Insns is
case Get_Expr_Mode (Left) is
when Mode_F32 .. Mode_F64 =>
-- fstp instruction.
- Reg_Res := R_St0;
+ if Abi.Flag_Sse2 then
+ Reg_Res := R_Any_Xmm;
+ else
+ Reg_Res := R_St0;
+ end if;
when others =>
-- Push instruction.
Reg_Res := R_Irm;
@@ -2015,7 +1991,7 @@ package body Ortho_Code.X86.Insns is
Link_Stmt (Gen_Call (Stmt, R_None, Num));
when OE_Ret =>
Left := Get_Expr_Operand (Stmt);
- P_Reg := Get_Call_Register (Get_Expr_Mode (Stmt));
+ P_Reg := Get_Return_Register (Get_Expr_Mode (Stmt));
Left := Gen_Insn (Left, P_Reg, Num);
Set_Expr_Operand (Stmt, Left);
Link_Stmt (Stmt);
@@ -2061,6 +2037,7 @@ package body Ortho_Code.X86.Insns is
Stmt : O_Enode;
N_Stmt : O_Enode;
begin
+ -- Handle --be-debug=i
if Debug.Flag_Debug_Insn then
declare
Inter : O_Dnode;
@@ -2074,12 +2051,14 @@ package body Ortho_Code.X86.Insns is
end;
end if;
+ -- Before the prologue, all registers are unused.
for I in Regs_R32 loop
Regs (I).Used := False;
end loop;
Stack_Max := 0;
Stack_Offset := 0;
+ Need_Fp_Conv_Slot := False;
First := Subprg.E_Entry;
Expand_Decls (Subprg.D_Body + 1);
Abi.Last_Link := First;
@@ -2094,13 +2073,18 @@ package body Ortho_Code.X86.Insns is
Stmt := N_Stmt;
end loop;
+ -- Allocate one stack slot for fp conversion for the whole subprogram.
+ if Need_Fp_Conv_Slot then
+ Stack_Max := Do_Align (Stack_Max, 8);
+ Stack_Max := Stack_Max + 8;
+ Subprg.Target.Fp_Slot := Stack_Max;
+ end if;
+
-- Keep stack depth for this subprogram.
Subprg.Stack_Max := Stack_Max;
-- Sanity check: there must be no remaining pushed bytes.
- if Push_Offset /= 0 then
- raise Program_Error with "gen_subprg_insn: push_offset not 0";
- end if;
+ pragma Assert (Push_Offset = 0);
end Gen_Subprg_Insns;
end Ortho_Code.X86.Insns;
diff --git a/src/ortho/mcode/ortho_code-x86-insns.ads b/src/ortho/mcode/ortho_code-x86-insns.ads
index 9411737a0..fc20ed522 100644
--- a/src/ortho/mcode/ortho_code-x86-insns.ads
+++ b/src/ortho/mcode/ortho_code-x86-insns.ads
@@ -15,11 +15,15 @@
-- along with GCC; see the file COPYING. If not, write to the Free
-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-- 02111-1307, USA.
+with Ortho_Code.Exprs; use Ortho_Code.Exprs;
+
package Ortho_Code.X86.Insns is
function Reg_Used (Reg : Regs_R32) return Boolean;
-- Split enodes of SUBPRG into instructions.
procedure Gen_Subprg_Insns (Subprg : Subprogram_Data_Acc);
+ -- Convert a KIND to a reg.
+ function Ekind_Unsigned_To_Cc (Kind : OE_Kind_Cmp) return O_Reg;
+ function Ekind_Signed_To_Cc (Kind : OE_Kind_Cmp) return O_Reg;
end Ortho_Code.X86.Insns;
-
diff --git a/src/ortho/mcode/ortho_code-x86.adb b/src/ortho/mcode/ortho_code-x86.adb
index 175dd7e99..3eb712957 100644
--- a/src/ortho/mcode/ortho_code-x86.adb
+++ b/src/ortho/mcode/ortho_code-x86.adb
@@ -68,42 +68,4 @@ package body Ortho_Code.X86 is
end case;
end Get_R64_Low;
- function Ekind_Unsigned_To_Cc (Kind : OE_Kind_Cmp) return O_Reg is
- begin
- case Kind is
- when OE_Eq =>
- return R_Eq;
- when OE_Neq =>
- return R_Ne;
- when OE_Lt =>
- return R_Ult;
- when OE_Le =>
- return R_Ule;
- when OE_Gt =>
- return R_Ugt;
- when OE_Ge =>
- return R_Uge;
- end case;
- end Ekind_Unsigned_To_Cc;
-
- function Ekind_Signed_To_Cc (Kind : OE_Kind_Cmp) return O_Reg is
- begin
- case Kind is
- when OE_Eq =>
- return R_Eq;
- when OE_Neq =>
- return R_Ne;
- when OE_Lt =>
- return R_Slt;
- when OE_Le =>
- return R_Sle;
- when OE_Gt =>
- return R_Sgt;
- when OE_Ge =>
- return R_Sge;
- end case;
- end Ekind_Signed_To_Cc;
-
end Ortho_Code.X86;
-
-
diff --git a/src/ortho/mcode/ortho_code-x86.ads b/src/ortho/mcode/ortho_code-x86.ads
index 24be1eb6c..817b7afec 100644
--- a/src/ortho/mcode/ortho_code-x86.ads
+++ b/src/ortho/mcode/ortho_code-x86.ads
@@ -15,7 +15,6 @@
-- along with GCC; see the file COPYING. If not, write to the Free
-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-- 02111-1307, USA.
-with Ortho_Code.Exprs; use Ortho_Code.Exprs;
package Ortho_Code.X86 is
-- Registers.
@@ -153,8 +152,4 @@ package Ortho_Code.X86 is
subtype Intrinsics_X86 is Int32
range Intrinsic_Mul_Ov_U64 .. Intrinsic_Rem_Ov_I64;
- -- Convert a KIND to a reg.
- function Ekind_Unsigned_To_Cc (Kind : OE_Kind_Cmp) return O_Reg;
- function Ekind_Signed_To_Cc (Kind : OE_Kind_Cmp) return O_Reg;
-
end Ortho_Code.X86;