aboutsummaryrefslogtreecommitdiffstats
path: root/src/ortho/mcode/ortho_code-x86-emits.adb
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2015-11-12 07:02:27 +0100
committerTristan Gingold <tgingold@free.fr>2015-11-12 07:02:27 +0100
commitd311f82ce7a565123f31bfab734489bcf4a51895 (patch)
treedeccbc0b769d3fd659d291aceea76b21da249906 /src/ortho/mcode/ortho_code-x86-emits.adb
parent15baf16d632f9425e8a955e0344a8376409db814 (diff)
downloadghdl-d311f82ce7a565123f31bfab734489bcf4a51895.tar.gz
ghdl-d311f82ce7a565123f31bfab734489bcf4a51895.tar.bz2
ghdl-d311f82ce7a565123f31bfab734489bcf4a51895.zip
mcode x86: pass testsuite with sse.
Diffstat (limited to 'src/ortho/mcode/ortho_code-x86-emits.adb')
-rw-r--r--src/ortho/mcode/ortho_code-x86-emits.adb299
1 files changed, 189 insertions, 110 deletions
diff --git a/src/ortho/mcode/ortho_code-x86-emits.adb b/src/ortho/mcode/ortho_code-x86-emits.adb
index 6aebd67c6..46a6423e6 100644
--- a/src/ortho/mcode/ortho_code-x86-emits.adb
+++ b/src/ortho/mcode/ortho_code-x86-emits.adb
@@ -97,7 +97,7 @@ package body Ortho_Code.X86.Emits is
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_Andp : constant := 16#54#;
Opc2_0f_Xorp : constant := 16#57#;
Opc_Call : constant := 16#e8#;
Opc_Jmp_Long : constant := 16#e9#;
@@ -717,14 +717,16 @@ package body Ortho_Code.X86.Emits is
end case;
end Mode_Fp_To_Mf;
- function Gen_Constant_Start return Symbol
+ subtype Nat_Align is Natural range 0 .. 4;
+
+ function Gen_Constant_Start (Log2sz : Nat_Align) return Symbol
is
Sym : Symbol;
begin
-- Write the constant in .rodata
Set_Current_Section (Sect_Rodata);
- Gen_Pow_Align (3);
- Prealloc (8);
+ Gen_Pow_Align (Log2sz);
+ Prealloc (2 ** Log2sz);
Sym := Create_Local_Symbol;
Set_Symbol_Pc (Sym, False);
return Sym;
@@ -734,7 +736,7 @@ package body Ortho_Code.X86.Emits is
is
Sym : Symbol;
begin
- Sym := Gen_Constant_Start;
+ Sym := Gen_Constant_Start (2);
Gen_Le32 (Val);
Set_Current_Section (Sect_Text);
return Sym;
@@ -744,13 +746,26 @@ package body Ortho_Code.X86.Emits is
is
Sym : Symbol;
begin
- Sym := Gen_Constant_Start;
+ Sym := Gen_Constant_Start (3);
Gen_Le32 (Lo);
Gen_Le32 (Hi);
Set_Current_Section (Sect_Text);
return Sym;
end Gen_Constant_64;
+ function Gen_Constant_128 (Lo, Hi : Unsigned_32) return Symbol
+ is
+ Sym : Symbol;
+ begin
+ Sym := Gen_Constant_Start (4);
+ Gen_Le32 (Lo);
+ Gen_Le32 (Hi);
+ Gen_Le32 (Lo);
+ Gen_Le32 (Hi);
+ Set_Current_Section (Sect_Text);
+ return Sym;
+ end Gen_Constant_128;
+
Xmm_Sign32_Sym : Symbol := Null_Symbol;
Xmm_Sign64_Sym : Symbol := Null_Symbol;
@@ -759,20 +774,43 @@ package body Ortho_Code.X86.Emits is
case Mode is
when Mode_F32 =>
if Xmm_Sign32_Sym = Null_Symbol then
- Xmm_Sign32_Sym := Gen_Constant_32 (16#8000_0000#);
+ Xmm_Sign32_Sym := Gen_Constant_128
+ (16#8000_0000#, 16#8000_0000#);
end if;
return Xmm_Sign32_Sym;
when Mode_F64 =>
if Xmm_Sign64_Sym = Null_Symbol then
- Xmm_Sign64_Sym := Gen_Constant_64 (0, 16#8000_0000#);
+ Xmm_Sign64_Sym := Gen_Constant_128
+ (0, 16#8000_0000#);
end if;
return Xmm_Sign64_Sym;
end case;
end Get_Xmm_Sign_Constant;
- procedure Gen_SSE_Rep_Opc (Sz : Mode_Fp; Opc : Byte) is
+ Xmm_Mask32_Sym : Symbol := Null_Symbol;
+ Xmm_Mask64_Sym : Symbol := Null_Symbol;
+
+ function Get_Xmm_Mask_Constant (Mode : Mode_Fp) return Symbol is
begin
- case Sz is
+ case Mode is
+ when Mode_F32 =>
+ if Xmm_Mask32_Sym = Null_Symbol then
+ Xmm_Mask32_Sym := Gen_Constant_128
+ (16#7fff_ffff#, 16#7fff_ffff#);
+ end if;
+ return Xmm_Mask32_Sym;
+ when Mode_F64 =>
+ if Xmm_Mask64_Sym = Null_Symbol then
+ Xmm_Mask64_Sym := Gen_Constant_128
+ (16#ffff_ffff#, 16#7fff_ffff#);
+ end if;
+ return Xmm_Mask64_Sym;
+ end case;
+ end Get_Xmm_Mask_Constant;
+
+ procedure Gen_SSE_Rep_Opc (Mode : Mode_Fp; Opc : Byte) is
+ begin
+ case Mode is
when Mode_F32 =>
Gen_B8 (16#f3#);
when Mode_F64 =>
@@ -782,9 +820,9 @@ package body Ortho_Code.X86.Emits is
Gen_B8 (Opc);
end Gen_SSE_Rep_Opc;
- procedure Gen_SSE_D16_Opc (Sz : Mode_Fp; Opc : Byte) is
+ procedure Gen_SSE_D16_Opc (Mode : Mode_Fp; Opc : Byte) is
begin
- case Sz is
+ case Mode is
when Mode_F32 =>
null;
when Mode_F64 =>
@@ -920,17 +958,26 @@ package body Ortho_Code.X86.Emits is
End_Insn;
end Emit_Store;
- procedure Emit_Store_Fp (Stmt : O_Enode; Sz : Mode_Fp)
- is
+ procedure Emit_Store_Fp (Stmt : O_Enode; Mode : Mode_Fp) is
begin
-- fstp
Start_Insn;
- Gen_B8 (2#11011_00_1# + Mode_Fp_To_Mf (Sz));
+ Gen_B8 (2#11011_00_1# + Mode_Fp_To_Mf (Mode));
Init_Modrm_Mem (Get_Assign_Target (Stmt), Sz_32l);
Gen_Mod_Rm (2#011_000#);
End_Insn;
end Emit_Store_Fp;
+ procedure Emit_Store_Xmm (Stmt : O_Enode; Mode : Mode_Fp) is
+ begin
+ -- movsd
+ Init_Modrm_Mem (Get_Assign_Target (Stmt), Sz_32l);
+ Start_Insn;
+ Gen_SSE_Rep_Opc (Mode, 16#11#);
+ Gen_Mod_Rm (To_Reg_Xmm (Get_Expr_Reg (Get_Expr_Operand (Stmt))) * 8);
+ End_Insn;
+ end Emit_Store_Xmm;
+
procedure Emit_Push_32 (Val : O_Enode; Sz : Insn_Size)
is
R : constant O_Reg := Get_Expr_Reg (Val);
@@ -1186,6 +1233,21 @@ package body Ortho_Code.X86.Emits is
End_Insn;
end Emit_Spill;
+ procedure Emit_Spill_Xmm (Stmt : O_Enode; Mode : Mode_Fp)
+ is
+ Expr : constant O_Enode := Get_Expr_Operand (Stmt);
+ Reg : constant O_Reg := Get_Expr_Reg (Expr);
+ begin
+ -- A reload is missing.
+ pragma Assert (Reg in Regs_Xmm);
+ -- movsd
+ Init_Modrm_Mem (Stmt, Sz_32l);
+ Start_Insn;
+ Gen_SSE_Rep_Opc (Mode, 16#11#);
+ Gen_Mod_Rm (To_Reg_Xmm (Reg) * 8);
+ End_Insn;
+ end Emit_Spill_Xmm;
+
procedure Emit_Load (Reg : O_Reg; Val : O_Enode; Sz : Insn_Size)
is
begin
@@ -1423,29 +1485,23 @@ package body Ortho_Code.X86.Emits is
Gen_Cmp_Imm (Reg_Res, 16#Ff#, Sz_32l);
Gen_Ov_Check (R_Ule);
when Mode_F64 =>
- Emit_Push_32 (Op, Sz_32l);
- -- fild (%esp)
- Start_Insn;
- Gen_B8 (2#11011_011#);
- 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#);
+ -- cvtsi2sd
+ Init_Rm_Expr (Op, Sz_32l);
+ Gen_SSE_Rep_Opc (Mode_F64, 16#2a#);
+ Gen_Mod_Rm (To_Reg_Xmm (Reg_Res) * 8);
End_Insn;
- -- movsd (%esp), %xmm
+ else
+ Emit_Push_32 (Op, Sz_32l);
+ -- fild (%esp)
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#11011_011#);
+ Gen_B8 (2#00_000_100#);
Gen_B8 (2#00_100_100#);
End_Insn;
+ -- addl %esp, 4
+ Emit_Addl_Sp_Imm (4);
end if;
- -- addl %esp, 4
- Emit_Addl_Sp_Imm (4);
when others =>
Error_Emit ("gen_conv_i32", Stmt);
end case;
@@ -1583,12 +1639,27 @@ package body Ortho_Code.X86.Emits is
procedure Gen_Conv_Fp (Stmt : O_Enode)
is
Reg : constant O_Reg := Get_Expr_Reg (Stmt);
+ Reg_Op : constant O_Reg := Get_Expr_Reg (Get_Expr_Operand (Stmt));
begin
+ Init_Modrm_Offset
+ (R_Bp, -Int32 (Cur_Subprg.Target.Fp_Slot), Sz_32l);
+
+ if Reg_Op in Regs_Xmm then
+ -- movsd %xmm, (%ebp),
+ Start_Insn;
+ Gen_SSE_Rep_Opc (Mode_F64, 16#11#);
+ Gen_Mod_Rm (To_Reg_Xmm (Reg_Op) * 8);
+ End_Insn;
+ -- fldl slot(%ebp)
+ Start_Insn;
+ Gen_B8 (2#11011_00_1# + Mode_Fp_To_Mf (Mode_F64));
+ Gen_Mod_Rm (2#00_000_000#);
+ End_Insn;
+ end if;
+
case Get_Expr_Mode (Stmt) is
when Mode_I32 =>
-- fistpl slot(%ebp)
- Init_Modrm_Offset
- (R_Bp, -Int32 (Cur_Subprg.Target.Fp_Slot), Sz_32l);
Start_Insn;
Gen_B8 (2#11011_011#);
Gen_Mod_Rm (2#00_011_000#);
@@ -1600,9 +1671,7 @@ package body Ortho_Code.X86.Emits is
Gen_Mod_Rm (To_Reg32 (Reg, Sz_32l) * 8);
End_Insn;
when Mode_I64 =>
- -- fistpq (%esp)
- Init_Modrm_Offset
- (R_Bp, -Int32 (Cur_Subprg.Target.Fp_Slot), Sz_32l);
+ -- fistpq slot(%ebp)
Start_Insn;
Gen_B8 (2#11011_111#);
Gen_Mod_Rm (2#00_111_000#);
@@ -1953,10 +2022,10 @@ package body Ortho_Code.X86.Emits is
| Mode_F64 =>
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);
+ -- Andp{sd} reg, cst
+ Init_Modrm_Sym (Get_Xmm_Mask_Constant (Mode), Sz_32l);
Start_Insn;
- Gen_SSE_D16_Opc (Mode, Opc2_0f_Andnp);
+ Gen_SSE_D16_Opc (Mode, Opc2_0f_Andp);
Gen_Mod_Rm (Xmm_To_Modrm_Reg (Reg));
End_Insn;
else
@@ -1968,68 +2037,81 @@ package body Ortho_Code.X86.Emits is
end case;
when OE_Kind_Cmp =>
- case Get_Expr_Mode (Get_Expr_Left (Stmt)) is
- when Mode_U32
- | Mode_I32
- | Mode_P32 =>
- Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_32l);
- when Mode_B2
- | Mode_I8
- | Mode_U8 =>
- Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_8);
- when Mode_U64 =>
- declare
- Pc : Pc_Type;
- begin
- Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_32h);
- -- jne
- Start_Insn;
- Gen_B8 (Opc_Jcc + 2#0101#);
- Gen_B8 (0);
- End_Insn;
- Pc := Get_Current_Pc;
- Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_32l);
- Patch_B8 (Pc - 1, Unsigned_8 (Get_Current_Pc - Pc));
- end;
- when Mode_I64 =>
- declare
- Pc : Pc_Type;
- begin
- Reg := Get_Expr_Reg (Stmt);
- 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, Insns.Ekind_Signed_To_Cc (Kind));
- -- jne
- Start_Insn;
- Gen_B8 (Opc_Jcc + 2#0101#);
- Gen_B8 (0);
- End_Insn;
- Pc := Get_Current_Pc;
+ declare
+ Left : constant O_Enode := Get_Expr_Left (Stmt);
+ Op_Mode : constant Mode_Type := Get_Expr_Mode (Left);
+ begin
+ case Op_Mode is
+ when Mode_U32
+ | Mode_I32
+ | Mode_P32 =>
Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_32l);
- Emit_Setcc_Reg (Reg, Insns.Ekind_Unsigned_To_Cc (Kind));
- Patch_B8 (Pc - 1, Unsigned_8 (Get_Current_Pc - Pc));
- return;
- end;
- when Mode_F32
- | Mode_F64 =>
- -- fcomip st, st(1)
- Start_Insn;
- Gen_B8 (2#11011_111#);
- Gen_B8 (2#1111_0001#);
- End_Insn;
- -- fstp st, st (0)
- Start_Insn;
- Gen_B8 (2#11011_101#);
- Gen_B8 (2#11_011_000#);
- End_Insn;
- when others =>
- Error_Emit ("emit_insn: cmp", Stmt);
- end case;
- Reg := Get_Expr_Reg (Stmt);
- if Reg not in Regs_Cc then
- Error_Emit ("emit_insn/cmp: not cc", Stmt);
- end if;
+ when Mode_B2
+ | Mode_I8
+ | Mode_U8 =>
+ Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_8);
+ when Mode_U64 =>
+ declare
+ Pc : Pc_Type;
+ begin
+ Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_32h);
+ -- jne
+ Start_Insn;
+ Gen_B8 (Opc_Jcc + 2#0101#);
+ Gen_B8 (0);
+ End_Insn;
+ Pc := Get_Current_Pc;
+ Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_32l);
+ Patch_B8 (Pc - 1, Unsigned_8 (Get_Current_Pc - Pc));
+ end;
+ when Mode_I64 =>
+ declare
+ Pc : Pc_Type;
+ begin
+ Reg := Get_Expr_Reg (Stmt);
+ 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, Insns.Ekind_Signed_To_Cc (Kind));
+ -- jne
+ Start_Insn;
+ Gen_B8 (Opc_Jcc + 2#0101#);
+ Gen_B8 (0);
+ End_Insn;
+ Pc := Get_Current_Pc;
+ Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_32l);
+ Emit_Setcc_Reg
+ (Reg, Insns.Ekind_Unsigned_To_Cc (Kind));
+ Patch_B8 (Pc - 1, Unsigned_8 (Get_Current_Pc - Pc));
+ return;
+ end;
+ when Mode_F32
+ | Mode_F64 =>
+ if Abi.Flag_Sse2 then
+ -- comisd %xmm, rm
+ Start_Insn;
+ Gen_SSE_D16_Opc (Op_Mode, 16#2f#);
+ Init_Rm_Expr (Get_Expr_Right (Stmt), Sz_32l);
+ Gen_Mod_Rm (To_Reg_Xmm (Get_Expr_Reg (Left)) * 8);
+ End_Insn;
+ else
+ -- fcomip st, st(1)
+ Start_Insn;
+ Gen_B8 (2#11011_111#);
+ Gen_B8 (2#1111_0001#);
+ End_Insn;
+ -- fstp st, st (0)
+ Start_Insn;
+ Gen_B8 (2#11011_101#);
+ Gen_B8 (2#11_011_000#);
+ End_Insn;
+ end if;
+ when others =>
+ Error_Emit ("emit_insn: cmp", Stmt);
+ end case;
+ -- Result is in eflags.
+ pragma Assert (Get_Expr_Reg (Stmt) in Regs_Cc);
+ end;
when OE_Const
| OE_Addrg =>
case Mode is
@@ -2105,7 +2187,11 @@ package body Ortho_Code.X86.Emits is
Emit_Store (Stmt, Sz_32l);
Emit_Store (Stmt, Sz_32h);
when Mode_Fp =>
- Emit_Store_Fp (Stmt, Mode);
+ if Abi.Flag_Sse2 then
+ Emit_Store_Xmm (Stmt, Mode);
+ else
+ Emit_Store_Fp (Stmt, Mode);
+ end if;
when others =>
Error_Emit ("emit_insn: move", Stmt);
end case;
@@ -2216,14 +2302,7 @@ package body Ortho_Code.X86.Emits is
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;
+ Emit_Spill_Xmm (Stmt, Mode);
when others =>
Error_Emit ("emit_insn: spill", Stmt);
end case;