From 15baf16d632f9425e8a955e0344a8376409db814 Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Wed, 11 Nov 2015 04:40:07 +0100 Subject: mcode x86: wip: sse support. --- src/ortho/mcode/ortho_code-exprs.adb | 5 +- src/ortho/mcode/ortho_code-exprs.ads | 5 + src/ortho/mcode/ortho_code-x86-abi.adb | 8 + src/ortho/mcode/ortho_code-x86-abi.ads | 12 +- src/ortho/mcode/ortho_code-x86-emits.adb | 401 +++++++++++++++++++++---------- src/ortho/mcode/ortho_code-x86-emits.ads | 2 +- src/ortho/mcode/ortho_code-x86-insns.adb | 252 +++++++++---------- src/ortho/mcode/ortho_code-x86-insns.ads | 6 +- src/ortho/mcode/ortho_code-x86.adb | 38 --- src/ortho/mcode/ortho_code-x86.ads | 5 - 10 files changed, 420 insertions(+), 314 deletions(-) (limited to 'src/ortho/mcode') 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; -- cgit v1.2.3