aboutsummaryrefslogtreecommitdiffstats
path: root/src/ortho/mcode/ortho_code-x86-emits.adb
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/mcode/ortho_code-x86-emits.adb
parent8b20df13007f67f5c25a9801e917ae4feea0826b (diff)
downloadghdl-15baf16d632f9425e8a955e0344a8376409db814.tar.gz
ghdl-15baf16d632f9425e8a955e0344a8376409db814.tar.bz2
ghdl-15baf16d632f9425e8a955e0344a8376409db814.zip
mcode x86: wip: sse support.
Diffstat (limited to 'src/ortho/mcode/ortho_code-x86-emits.adb')
-rw-r--r--src/ortho/mcode/ortho_code-x86-emits.adb401
1 files changed, 271 insertions, 130 deletions
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