aboutsummaryrefslogtreecommitdiffstats
path: root/src/ortho/mcode/ortho_code-x86-emits.adb
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2015-01-22 04:42:30 +0100
committerTristan Gingold <tgingold@free.fr>2015-01-22 04:42:30 +0100
commit6caa543e9416d3a8bfc50b6f6da4b502a8069029 (patch)
tree6a9bde19612fc2b76552735109b156914eb1d902 /src/ortho/mcode/ortho_code-x86-emits.adb
parentbcd53686ad09a434a81fc8ccf092ed16f454cd5c (diff)
downloadghdl-6caa543e9416d3a8bfc50b6f6da4b502a8069029.tar.gz
ghdl-6caa543e9416d3a8bfc50b6f6da4b502a8069029.tar.bz2
ghdl-6caa543e9416d3a8bfc50b6f6da4b502a8069029.zip
mcode x86: handle more conversions (i64 <-> u8. b2)
Diffstat (limited to 'src/ortho/mcode/ortho_code-x86-emits.adb')
-rw-r--r--src/ortho/mcode/ortho_code-x86-emits.adb104
1 files changed, 64 insertions, 40 deletions
diff --git a/src/ortho/mcode/ortho_code-x86-emits.adb b/src/ortho/mcode/ortho_code-x86-emits.adb
index 27f78ef47..34ff58cd0 100644
--- a/src/ortho/mcode/ortho_code-x86-emits.adb
+++ b/src/ortho/mcode/ortho_code-x86-emits.adb
@@ -1123,34 +1123,26 @@ package body Ortho_Code.X86.Emits is
-- Convert U32 to xx.
procedure Gen_Conv_U32 (Stmt : O_Enode)
is
- Op : O_Enode;
- Reg_Op : O_Reg;
- Reg_Res : O_Reg;
+ Op : constant O_Enode := Get_Expr_Operand (Stmt);
+ Reg_Op : constant O_Reg := Get_Expr_Reg (Op);
+ Reg_Res : constant O_Reg := Get_Expr_Reg (Stmt);
begin
- Op := Get_Expr_Operand (Stmt);
- Reg_Op := Get_Expr_Reg (Op);
- Reg_Res := Get_Expr_Reg (Stmt);
case Get_Expr_Mode (Stmt) is
when Mode_I32 =>
- if Reg_Res not in Regs_R32 then
- raise Program_Error;
- end if;
+ pragma Assert (Reg_Res in Regs_R32);
if Reg_Op /= Reg_Res then
Emit_Load (Reg_Res, Op, Sz_32l);
end if;
Emit_Tst (Reg_Res, Sz_32l);
Gen_Ov_Check (R_Sge);
when Mode_I64 =>
- if Reg_Res /= R_Edx_Eax or Reg_Op /= R_Ax then
- raise Program_Error;
- end if;
+ pragma Assert (Reg_Res = R_Edx_Eax);
+ pragma Assert (Reg_Op = R_Ax);
-- Clear edx.
Gen_Clear_Edx;
when Mode_U8
| Mode_B2 =>
- if Reg_Res not in Regs_R32 then
- raise Program_Error;
- end if;
+ pragma Assert (Reg_Res in Regs_R32);
if Reg_Op /= Reg_Res then
Emit_Load (Reg_Res, Op, Sz_32l);
end if;
@@ -1169,23 +1161,17 @@ package body Ortho_Code.X86.Emits is
-- Convert I32 to xxx
procedure Gen_Conv_I32 (Stmt : O_Enode)
is
- Op : O_Enode;
- Reg_Op : O_Reg;
- Reg_Res : O_Reg;
+ Op : constant O_Enode := Get_Expr_Operand (Stmt);
+ Reg_Op : constant O_Reg := Get_Expr_Reg (Op);
+ Reg_Res : constant O_Reg := Get_Expr_Reg (Stmt);
begin
- Op := Get_Expr_Operand (Stmt);
- Reg_Op := Get_Expr_Reg (Op);
- Reg_Res := Get_Expr_Reg (Stmt);
case Get_Expr_Mode (Stmt) is
when Mode_I64 =>
- if Reg_Res /= R_Edx_Eax or Reg_Op /= R_Ax then
- raise Program_Error;
- end if;
+ pragma Assert (Reg_Res = R_Edx_Eax);
+ pragma Assert (Reg_Op = R_Ax);
Gen_Cdq;
when Mode_U32 =>
- if Reg_Res not in Regs_R32 then
- raise Program_Error;
- end if;
+ pragma Assert (Reg_Res in Regs_R32);
if Reg_Op /= Reg_Res then
Emit_Load (Reg_Res, Op, Sz_32l);
end if;
@@ -1225,20 +1211,24 @@ package body Ortho_Code.X86.Emits is
-- Convert U8 to xxx
procedure Gen_Conv_U8 (Stmt : O_Enode)
is
- Op : O_Enode;
- Reg_Res : O_Reg;
+ Op : constant O_Enode := Get_Expr_Operand (Stmt);
+ Reg_Res : constant O_Reg := Get_Expr_Reg (Stmt);
+ Reg_Op : constant O_Reg := Get_Expr_Reg (Op);
begin
- Op := Get_Expr_Operand (Stmt);
- Reg_Res := Get_Expr_Reg (Stmt);
case Get_Expr_Mode (Stmt) is
when Mode_U32
| Mode_I32
| Mode_U16
| Mode_I16 =>
- if Reg_Res not in Regs_R32 then
- raise Program_Error;
- end if;
+ pragma Assert (Reg_Res in Regs_R32);
Gen_Movzx (Reg_Res, Op, Sz_8);
+ when Mode_I64
+ | Mode_U64 =>
+ pragma Assert (Reg_Res = R_Edx_Eax);
+ pragma Assert (Reg_Op = R_Ax);
+ Gen_Movzx (R_Ax, Op, Sz_8);
+ -- Sign-extend, but we know the sign is positive.
+ Gen_Cdq;
when others =>
Error_Emit ("gen_conv_U8", Stmt);
end case;
@@ -1247,17 +1237,23 @@ package body Ortho_Code.X86.Emits is
-- Convert B2 to xxx
procedure Gen_Conv_B2 (Stmt : O_Enode)
is
- Op : O_Enode;
- Reg_Res : O_Reg;
+ Op : constant O_Enode := Get_Expr_Operand (Stmt);
+ Reg_Op : constant O_Reg := Get_Expr_Reg (Op);
+ Reg_Res : constant O_Reg := Get_Expr_Reg (Stmt);
begin
- Op := Get_Expr_Operand (Stmt);
- Reg_Res := Get_Expr_Reg (Stmt);
case Get_Expr_Mode (Stmt) is
when Mode_U32
| Mode_I32
| Mode_U16
| Mode_I16 =>
+ pragma Assert (Reg_Res in Regs_R32);
Gen_Movzx (Reg_Res, Op, Sz_8);
+ when Mode_I64 =>
+ pragma Assert (Reg_Res = R_Edx_Eax);
+ pragma Assert (Reg_Op = R_Ax);
+ Gen_Movzx (R_Ax, Op, Sz_8);
+ -- Sign-extend, but we know the sign is positive.
+ Gen_Cdq;
when others =>
Error_Emit ("gen_conv_B2", Stmt);
end case;
@@ -1266,23 +1262,50 @@ package body Ortho_Code.X86.Emits is
-- Convert I64 to xxx
procedure Gen_Conv_I64 (Stmt : O_Enode)
is
- Op : O_Enode;
+ Op : constant O_Enode := Get_Expr_Operand (Stmt);
+ Reg_Op : constant O_Reg := Get_Expr_Reg (Op);
+ Reg_Res : constant O_Reg := Get_Expr_Reg (Stmt);
begin
- Op := Get_Expr_Operand (Stmt);
case Get_Expr_Mode (Stmt) is
when Mode_I32 =>
+ pragma Assert (Reg_Op = R_Edx_Eax);
+ pragma Assert (Reg_Res = R_Ax);
-- move dx to reg_helper
Start_Insn;
Gen_B8 (2#1000_1001#);
Gen_B8 (2#11_010_000# + To_Reg32 (Reg_Helper));
End_Insn;
+ -- Sign extend eax.
Gen_Cdq;
-- cmp reg_helper, dx
Start_Insn;
Gen_B8 (2#0011_1001#);
Gen_B8 (2#11_010_000# + To_Reg32 (Reg_Helper));
End_Insn;
+ -- Overflow if extended value is different from initial value.
+ Gen_Ov_Check (R_Eq);
+ when Mode_U8 =>
+ pragma Assert (Reg_Op in Regs_R64);
+ -- Check MSB = 0
+ Emit_Tst (Reg_Op, Sz_32h);
Gen_Ov_Check (R_Eq);
+ -- Check LSB <= 255
+ if Reg_Op /= Reg_Res then
+ Emit_Load (Reg_Res, Op, Sz_32l);
+ end if;
+ Gen_Cmp_Imm (Reg_Res, 16#Ff#, Sz_32l);
+ Gen_Ov_Check (R_Ule);
+ when Mode_B2 =>
+ pragma Assert (Reg_Op in Regs_R64);
+ -- Check MSB = 0
+ Emit_Tst (Reg_Op, Sz_32h);
+ Gen_Ov_Check (R_Eq);
+ -- Check LSB <= 1
+ if Reg_Op /= Reg_Res then
+ Emit_Load (Reg_Res, Op, Sz_32l);
+ end if;
+ Gen_Cmp_Imm (Reg_Res, 16#1#, Sz_32l);
+ Gen_Ov_Check (R_Ule);
when Mode_F64 =>
Emit_Push_32 (Op, Sz_32h);
Emit_Push_32 (Op, Sz_32l);
@@ -1775,6 +1798,7 @@ package body Ortho_Code.X86.Emits is
end case;
when OE_Conv =>
+ -- Call Gen_Conv_FROM
case Get_Expr_Mode (Get_Expr_Operand (Stmt)) is
when Mode_U32 =>
Gen_Conv_U32 (Stmt);