summaryrefslogtreecommitdiff
path: root/src/ortho
diff options
context:
space:
mode:
Diffstat (limited to 'src/ortho')
-rw-r--r--src/ortho/mcode/ortho_code-x86-emits.adb658
1 files changed, 342 insertions, 316 deletions
diff --git a/src/ortho/mcode/ortho_code-x86-emits.adb b/src/ortho/mcode/ortho_code-x86-emits.adb
index ff48b10..4e374e4 100644
--- a/src/ortho/mcode/ortho_code-x86-emits.adb
+++ b/src/ortho/mcode/ortho_code-x86-emits.adb
@@ -46,10 +46,61 @@ package body Ortho_Code.X86.Emits is
-- x86 opcodes.
Opc_Data16 : constant := 16#66#;
+ Opc_Into : constant := 16#ce#;
+ Opc_Cdq : constant := 16#99#;
+ Opc_Int : constant := 16#cd#;
+ Opc_Addl_Reg_Rm : constant := 16#03#;
+ Opc_Xorl_Rm_Reg : constant := 16#31#;
+ Opc_Subl_Reg_Rm : constant := 16#2b#; -- Reg <- Reg - Rm
+ Opc_Cmpl_Rm_Reg : constant := 16#39#;
+ Opc_Leal_Reg_Rm : constant := 16#8d#;
Opc_Movb_Imm_Reg : constant := 16#b0#;
Opc_Movl_Imm_Reg : constant := 16#b8#;
- Opc_Mov_Rm_Imm : constant := 16#c6#; -- Eb, Ib or Ev, Iz
- Opc_Mov_Rm_Reg : constant := 16#88#; -- Eb, Gb or Ev, Gv
+ Opc_Imul_Reg_Rm_Imm32 : constant := 16#69#;
+ Opc_Imul_Reg_Rm_Imm8 : constant := 16#6b#;
+ 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_Grp1_Rm_Imm : constant := 16#80#;
+ Opc_Grp1b_Rm_Imm8 : constant := 16#80#;
+ Opc_Grp1v_Rm_Imm32 : constant := 16#81#;
+ -- Opc_Grp1b_Rm_Imm8 : constant := 16#82#; -- Should not be used.
+ Opc_Grp1v_Rm_Imm8 : constant := 16#83#;
+ Opc2_Grp1_Add : constant := 2#000_000#; -- Second byte
+ Opc2_Grp1_Or : constant := 2#001_000#; -- Second byte
+ Opc2_Grp1_Adc : constant := 2#010_000#; -- Second byte
+ Opc2_Grp1_Sbb : constant := 2#011_000#; -- Second byte
+ Opc2_Grp1_And : constant := 2#100_000#; -- Second byte
+ Opc2_Grp1_Sub : constant := 2#101_000#; -- Second byte
+ Opc2_Grp1_Xor : constant := 2#110_000#; -- Second byte
+ Opc2_Grp1_Cmp : constant := 2#111_000#; -- Second byte
+ Opc_Grp3_Width : constant := 16#f6#;
+ Opc2_Grp3_Not : constant := 2#010_000#;
+ Opc2_Grp3_Neg : constant := 2#011_000#;
+ Opc2_Grp3_Mul : constant := 2#100_000#;
+ Opc2_Grp3_Imul : constant := 2#101_000#;
+ Opc2_Grp3_Div : constant := 2#110_000#;
+ Opc2_Grp3_Idiv : constant := 2#111_000#;
+ Opc_Test_Rm_Reg : constant := 16#84#; -- Eb,Gb or Ev,Gv
+ Opc_Push_Imm8 : constant := 16#6a#;
+ Opc_Push_Imm : constant := 16#68#;
+ Opc_Push_Reg : constant := 16#50#; -- opc[2:0] is reg.
+ 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_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#;
+ Opc_Call : constant := 16#e8#;
+ Opc_Jmp_Long : constant := 16#e9#;
+ Opc_Jmp_Short : constant := 16#eb#;
+ Opc_Ret : constant := 16#c3#;
+ Opc_Leave : constant := 16#c9#;
procedure Error_Emit (Msg : String; Insn : O_Enode)
is
@@ -75,7 +126,7 @@ package body Ortho_Code.X86.Emits is
when Sz_8 =>
Gen_B8 (B);
when Sz_16 =>
- Gen_B8 (16#66#);
+ Gen_B8 (Opc_Data16);
Gen_B8 (B + 1);
when Sz_32l
| Sz_32h =>
@@ -89,7 +140,7 @@ package body Ortho_Code.X86.Emits is
when Sz_8 =>
Gen_B8 (B);
when Sz_16 =>
- Gen_B8 (16#66#);
+ Gen_B8 (Opc_Data16);
Gen_B8 (B + 3);
when Sz_32l
| Sz_32h =>
@@ -197,6 +248,11 @@ package body Ortho_Code.X86.Emits is
Rm_Offset : Int32;
Rm_Sym : Symbol;
+ -- If not R_Nil, encode mod=11 (no memory access). All above variables
+ -- must be 0/R_Nil.
+ Rm_Reg : O_Reg;
+ Rm_Sz : Insn_Size;
+
procedure Fill_Sib (N : O_Enode)
is
use Ortho_Code.Decls;
@@ -252,6 +308,7 @@ package body Ortho_Code.X86.Emits is
function To_Reg32 (R : O_Reg) return Byte is
begin
+ pragma Assert (R in Regs_R32);
return O_Reg'Pos (R) - O_Reg'Pos (R_Ax);
end To_Reg32;
pragma Inline (To_Reg32);
@@ -319,12 +376,27 @@ package body Ortho_Code.X86.Emits is
+ Base);
end Gen_Sib;
+ procedure Init_Modrm_Reg (Reg : O_Reg; Sz : Insn_Size) is
+ begin
+ Rm_Base := R_Nil;
+ SIB_Index := R_Nil;
+ SIB_Scale := 0;
+ Rm_Sym := Null_Symbol;
+ Rm_Offset := 0;
+
+ Rm_Reg := Reg;
+ Rm_Sz := Sz;
+ end Init_Modrm_Reg;
+
procedure Init_Rm_Mem (N : O_Enode; Sz : Insn_Size)
is
Reg : constant O_Reg := Get_Expr_Reg (N);
begin
Rm_Base := R_Nil;
SIB_Index := R_Nil;
+ Rm_Reg := R_Nil;
+ Rm_Sz := Sz;
+
if Sz = Sz_32h then
Rm_Offset := 4;
else
@@ -351,12 +423,26 @@ package body Ortho_Code.X86.Emits is
end case;
end Init_Rm_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);
+ else
+ -- Destination is an effective address.
+ Init_Rm_Mem (N, Sz);
+ end if;
+ end Init_Rm_Expr;
+
-- Generate an R/M (+ SIB) byte.
-- R is added to the R/M byte.
- procedure Gen_Rm_Mem (R : Byte) is
+ procedure Gen_Mod_Rm (R : Byte) is
begin
-- Emit bytes.
if SIB_Index /= R_Nil then
+ pragma Assert (Rm_Reg = R_Nil);
-- SIB.
if Rm_Base = R_Nil then
-- No base (but index). Use the special encoding with base=BP.
@@ -384,6 +470,15 @@ package body Ortho_Code.X86.Emits is
end if;
-- No SIB.
+ if Rm_Reg /= R_Nil then
+ -- Mod is register, no memory access.
+ 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));
+ return;
+ end if;
+
case Rm_Base is
when R_Sp =>
-- It isn't possible to use SP as a base register without using
@@ -417,7 +512,7 @@ package body Ortho_Code.X86.Emits is
when others =>
raise Program_Error;
end case;
- end Gen_Rm_Mem;
+ end Gen_Mod_Rm;
procedure Gen_Rm (R : Byte; N : O_Enode; Sz : Insn_Size)
is
@@ -429,19 +524,17 @@ package body Ortho_Code.X86.Emits is
else
-- Destination is an effective address.
Init_Rm_Mem (N, Sz);
- Gen_Rm_Mem (R);
+ Gen_Mod_Rm (R);
end if;
end Gen_Rm;
- procedure Emit_Op (Op : Byte; Stmt : O_Enode; Sz : Insn_Size)
+ procedure Gen_Grp1_Insn (Op : Byte; Stmt : O_Enode; Sz : Insn_Size)
is
- L, R : O_Enode;
- Lr, Rr : O_Reg;
+ L : constant O_Enode := Get_Expr_Left (Stmt);
+ R : constant O_Enode := Get_Expr_Right (Stmt);
+ Lr : constant O_Reg := Get_Expr_Reg (L);
+ Rr : constant O_Reg := Get_Expr_Reg (R);
begin
- L := Get_Expr_Left (Stmt);
- R := Get_Expr_Right (Stmt);
- Lr := Get_Expr_Reg (L);
- Rr := Get_Expr_Reg (R);
Start_Insn;
case Rr is
when R_Imm =>
@@ -467,7 +560,7 @@ package body Ortho_Code.X86.Emits is
Error_Emit ("emit_op", Stmt);
end case;
End_Insn;
- end Emit_Op;
+ end Gen_Grp1_Insn;
-- Emit a one byte instruction.
procedure Gen_1 (B : Byte) is
@@ -486,42 +579,77 @@ package body Ortho_Code.X86.Emits is
End_Insn;
end Gen_2;
+ -- Grp1 instructions have a mod/rm and an immediate value VAL.
+ -- Mod/Rm must be initialized.
+ procedure Gen_Insn_Grp1 (Opc2 : Byte; Sz : Insn_Size; Val : Int32) is
+ begin
+ Start_Insn;
+ if Val in -128 .. 127 then
+ case Sz is
+ when Sz_8 =>
+ Gen_B8 (Opc_Grp1b_Rm_Imm8);
+ when Sz_16 =>
+ Gen_B8 (Opc_Data16);
+ Gen_B8 (Opc_Grp1v_Rm_Imm8);
+ when Sz_32l
+ | Sz_32h =>
+ Gen_B8 (Opc_Grp1v_Rm_Imm8);
+ end case;
+ Gen_Mod_Rm (Opc2);
+ Gen_B8 (Byte (To_Uns32 (Val) and 16#Ff#));
+ else
+ case Sz is
+ when Sz_8 =>
+ pragma Assert (False);
+ null;
+ when Sz_16 =>
+ Gen_B8 (Opc_Data16);
+ Gen_B8 (Opc_Grp1v_Rm_Imm32);
+ when Sz_32l
+ | Sz_32h =>
+ Gen_B8 (Opc_Grp1v_Rm_Imm32);
+ end case;
+ Gen_Mod_Rm (Opc2);
+ Gen_Le32 (Unsigned_32 (To_Uns32 (Val)));
+ end if;
+ End_Insn;
+ end Gen_Insn_Grp1;
+
procedure Gen_Into is
begin
- Gen_1 (2#1100_1110#);
+ Gen_1 (Opc_Into);
end Gen_Into;
procedure Gen_Cdq is
begin
- Gen_1 (2#1001_1001#);
+ Gen_1 (Opc_Cdq);
end Gen_Cdq;
procedure Gen_Clear_Edx is
begin
-- Xorl edx, edx
- Gen_2 (2#0011_0001#, 2#11_010_010#);
+ Gen_2 (Opc_Xorl_Rm_Reg, 2#11_010_010#);
end Gen_Clear_Edx;
- procedure Gen_Mono_Op (Op : Byte; Val : O_Enode; Sz : Insn_Size) is
+ procedure Gen_Grp3_Insn (Op : Byte; Val : O_Enode; Sz : Insn_Size) is
begin
Start_Insn;
-- Unary Group 3 (test, not, neg...)
- Gen_Insn_Sz (2#1111_011_0#, Sz);
+ Gen_Insn_Sz (Opc_Grp3_Width, Sz);
Gen_Rm (Op, Val, Sz);
End_Insn;
- end Gen_Mono_Op;
+ end Gen_Grp3_Insn;
- procedure Emit_Mono_Op_Stmt (Op : Byte; Stmt : O_Enode; Sz : Insn_Size)
+ procedure Gen_Grp3_Insn_Stmt (Op : Byte; Stmt : O_Enode; Sz : Insn_Size)
is
begin
- Gen_Mono_Op (Op, Get_Expr_Operand (Stmt), Sz);
- end Emit_Mono_Op_Stmt;
+ Gen_Grp3_Insn (Op, Get_Expr_Operand (Stmt), Sz);
+ end Gen_Grp3_Insn_Stmt;
procedure Emit_Load_Imm (Stmt : O_Enode; Sz : Insn_Size)
is
- Tr : O_Reg;
+ Tr : constant O_Reg := Get_Expr_Reg (Stmt);
begin
- Tr := Get_Expr_Reg (Stmt);
Start_Insn;
-- TODO: handle 0 specially: use xor
-- Mov immediate.
@@ -660,7 +788,7 @@ package body Ortho_Code.X86.Emits is
Gen_B8 (16#0f#);
Gen_B8 (Opc);
Init_Rm_Mem (Mem, Sz_32l);
- Gen_Rm_Mem (Xmm_To_Modrm_Reg (Dest));
+ Gen_Mod_Rm (Xmm_To_Modrm_Reg (Dest));
End_Insn;
end Gen_Xmm_Modrm;
@@ -674,7 +802,7 @@ package body Ortho_Code.X86.Emits is
Start_Insn;
Gen_B8 (2#11011_001# + Mode_Fp_To_Mf (Sz));
Init_Rm_Mem (Get_Expr_Operand (Stmt), Sz_32l);
- Gen_Rm_Mem (2#000_000#);
+ Gen_Mod_Rm (2#000_000#);
End_Insn;
end if;
end Emit_Load_Fp_Mem;
@@ -691,18 +819,14 @@ package body Ortho_Code.X86.Emits is
| Regs_R64 =>
-- mov REG, OP
Start_Insn;
- Gen_Insn_Sz (2#1000_101_0#, Sz);
+ Gen_Insn_Sz (Opc_Mov_Reg_Rm, Sz);
Init_Rm_Mem (Val, Sz);
- Gen_Rm_Mem (To_Reg32 (Tr, Sz) * 8);
+ Gen_Mod_Rm (To_Reg32 (Tr, Sz) * 8);
End_Insn;
when R_Eq =>
-- Cmp OP, 1
- Start_Insn;
- Gen_Insn_Sz_S8 (2#1000_000_0#, Sz);
Init_Rm_Mem (Val, Sz);
- Gen_Rm_Mem (2#111_000#);
- Gen_B8 (1);
- End_Insn;
+ Gen_Insn_Grp1 (Opc2_Grp1_Cmp, Sz, 1);
when others =>
Error_Emit ("emit_load_mem", Stmt);
end case;
@@ -711,14 +835,12 @@ package body Ortho_Code.X86.Emits is
procedure Emit_Store (Stmt : O_Enode; Sz : Insn_Size)
is
- T, R : O_Enode;
- Tr, Rr : O_Reg;
+ T : constant O_Enode := Get_Assign_Target (Stmt);
+ R : constant O_Enode := Get_Expr_Operand (Stmt);
+ Tr : constant O_Reg := Get_Expr_Reg (T);
+ Rr : constant O_Reg := Get_Expr_Reg (R);
B : Byte;
begin
- T := Get_Assign_Target (Stmt);
- R := Get_Expr_Operand (Stmt);
- Tr := Get_Expr_Reg (T);
- Rr := Get_Expr_Reg (R);
Start_Insn;
case Rr is
when R_Imm =>
@@ -735,16 +857,16 @@ package body Ortho_Code.X86.Emits is
end case;
Gen_B8 (B + To_Reg32 (Tr, Sz));
else
- Gen_Insn_Sz (Opc_Mov_Rm_Imm, Sz);
Init_Rm_Mem (T, Sz);
- Gen_Rm_Mem (16#00#);
+ Gen_Insn_Sz (Opc_Mov_Rm_Imm, Sz);
+ Gen_Mod_Rm (16#00#);
end if;
Gen_Imm (R, Sz);
when Regs_R32
| Regs_R64 =>
Gen_Insn_Sz (Opc_Mov_Rm_Reg, Sz);
Init_Rm_Mem (T, Sz);
- Gen_Rm_Mem (To_Reg32 (Rr, Sz) * 8);
+ Gen_Mod_Rm (To_Reg32 (Rr, Sz) * 8);
when others =>
Error_Emit ("emit_store", Stmt);
end case;
@@ -758,67 +880,81 @@ package body Ortho_Code.X86.Emits is
Start_Insn;
Gen_B8 (2#11011_00_1# + Mode_Fp_To_Mf (Sz));
Init_Rm_Mem (Get_Assign_Target (Stmt), Sz_32l);
- Gen_Rm_Mem (2#011_000#);
+ Gen_Mod_Rm (2#011_000#);
End_Insn;
end Emit_Store_Fp;
procedure Emit_Push_32 (Val : O_Enode; Sz : Insn_Size)
is
- R : O_Reg;
+ R : constant O_Reg := Get_Expr_Reg (Val);
begin
- R := Get_Expr_Reg (Val);
Start_Insn;
case R is
when R_Imm =>
if Is_Imm8 (Val, Sz) then
- Gen_B8 (2#0110_1010#);
+ Gen_B8 (Opc_Push_Imm8);
Gen_Imm8 (Val, Sz);
else
- Gen_B8 (2#0110_1000#);
+ Gen_B8 (Opc_Push_Imm);
Gen_Imm (Val, Sz);
end if;
when Regs_R32
| Regs_R64 =>
- Gen_B8 (2#01010_000# + To_Reg32 (R, Sz));
+ Gen_B8 (Opc_Push_Reg + To_Reg32 (R, Sz));
when others =>
- Gen_B8 (2#1111_1111#);
- Gen_Rm (2#110_000#, Val, Sz);
+ Gen_B8 (Opc_Grp5);
+ Gen_Rm (Opc2_Grp5_Push_Rm, Val, Sz);
end case;
End_Insn;
end Emit_Push_32;
procedure Emit_Pop_32 (Val : O_Enode; Sz : Insn_Size)
is
- R : O_Reg;
+ R : constant O_Reg := Get_Expr_Reg (Val);
begin
- R := Get_Expr_Reg (Val);
Start_Insn;
case R is
when Regs_R32
| Regs_R64 =>
- Gen_B8 (2#01011_000# + To_Reg32 (R, Sz));
+ Gen_B8 (Opc_Pop_Reg + To_Reg32 (R, Sz));
when others =>
- Gen_B8 (2#1000_1111#);
- Gen_Rm (2#000_000#, Val, Sz);
+ 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;
+ Gen_B8 (Opc_Grp1v_Rm_Imm8);
+ Gen_B8 (Opc2_Grp1_Sub + 2#11_000_100#);
+ Gen_B8 (Len);
+ End_Insn;
+ end Emit_Subl_Sp_Imm;
+
+ procedure Emit_Addl_Sp_Imm (Len : Byte) is
+ begin
+ Start_Insn;
+ Gen_B8 (Opc_Grp1v_Rm_Imm8);
+ Gen_B8 (Opc2_Grp1_Add + 2#11_000_100#);
+ Gen_B8 (Len);
+ End_Insn;
+ end Emit_Addl_Sp_Imm;
+
procedure Emit_Push_Fp (Op : O_Enode; Sz : Mode_Fp)
is
pragma Unreferenced (Op);
+ Len : Byte;
begin
- Start_Insn;
-- subl esp, val
- Gen_B8 (2#100000_11#);
- Gen_B8 (2#11_101_100#);
case Sz is
when Mode_F32 =>
- Gen_B8 (4);
+ Len := 4;
when Mode_F64 =>
- Gen_B8 (8);
+ Len := 8;
end case;
- End_Insn;
+ Emit_Subl_Sp_Imm (Len);
-- fstp st, (esp)
Start_Insn;
Gen_B8 (2#11011_001# + Mode_Fp_To_Mf (Sz));
@@ -851,18 +987,18 @@ package body Ortho_Code.X86.Emits is
Opc := To_Cond (Reg);
if Val = 0 then
-- Assume long jmp.
- Gen_B8 (16#0f#);
- Gen_B8 (16#80# + Opc);
+ Gen_B8 (Opc_0f);
+ Gen_B8 (Opc2_0f_Jcc + Opc);
Gen_X86_Pc32 (Sym);
else
if Val + 128 < Get_Current_Pc + 4 then
-- Long jmp.
- Gen_B8 (16#0f#);
- Gen_B8 (16#80# + Opc);
+ Gen_B8 (Opc_0f);
+ Gen_B8 (Opc2_0f_Jcc + Opc);
Gen_Le32 (Unsigned_32 (Val - (Get_Current_Pc + 4)));
else
-- short jmp.
- Gen_B8 (16#70# + Opc);
+ Gen_B8 (Opc_Jcc + Opc);
Gen_B8 (Byte (Val - (Get_Current_Pc + 1)));
end if;
end if;
@@ -879,16 +1015,16 @@ package body Ortho_Code.X86.Emits is
Start_Insn;
if Val = 0 then
-- Assume long jmp.
- Gen_B8 (16#e9#);
+ Gen_B8 (Opc_Jmp_Long);
Gen_X86_Pc32 (Sym);
else
if Val + 128 < Get_Current_Pc + 4 then
-- Long jmp.
- Gen_B8 (16#e9#);
+ Gen_B8 (Opc_Jmp_Long);
Gen_Le32 (Unsigned_32 (Val - (Get_Current_Pc + 4)));
else
-- short jmp.
- Gen_B8 (16#eb#);
+ Gen_B8 (Opc_Jmp_Short);
Gen_B8 (Byte ((Val - (Get_Current_Pc + 1)) and 16#Ff#));
end if;
end if;
@@ -906,7 +1042,7 @@ package body Ortho_Code.X86.Emits is
procedure Gen_Call (Sym : Symbol) is
begin
Start_Insn;
- Gen_B8 (16#E8#);
+ Gen_B8 (Opc_Call);
Gen_X86_Pc32 (Sym);
End_Insn;
end Gen_Call;
@@ -916,61 +1052,40 @@ package body Ortho_Code.X86.Emits is
Val : constant Int32 := Get_Stack_Adjust (Stmt);
begin
if Val > 0 then
- Start_Insn;
-- subl esp, val
- Gen_B8 (2#100000_11#);
- Gen_B8 (2#11_101_100#);
- Gen_B8 (Byte (Val));
- End_Insn;
+ Emit_Subl_Sp_Imm (Byte (Val));
elsif Val < 0 then
- Start_Insn;
- if -Val <= 127 then
- -- addl esp, val
- Gen_B8 (2#100000_11#);
- Gen_B8 (2#11_000_100#);
- Gen_B8 (Byte (-Val));
- else
- -- addl esp, val
- Gen_B8 (2#100000_01#);
- Gen_B8 (2#11_000_100#);
- Gen_Le32 (Unsigned_32 (-Val));
- end if;
- End_Insn;
+ Init_Modrm_Reg (R_Sp, Sz_32l);
+ Gen_Insn_Grp1 (Opc2_Grp1_Add, Sz_32l, -Val);
end if;
end Emit_Setup_Frame;
procedure Emit_Call (Stmt : O_Enode)
is
use Ortho_Code.Decls;
- Subprg : O_Dnode;
- Sym : Symbol;
+ Subprg : constant O_Dnode := Get_Call_Subprg (Stmt);
+ Sym : constant Symbol := Get_Decl_Symbol (Subprg);
begin
- Subprg := Get_Call_Subprg (Stmt);
- Sym := Get_Decl_Symbol (Subprg);
Gen_Call (Sym);
end Emit_Call;
procedure Emit_Intrinsic (Stmt : O_Enode)
is
- Op : Int32;
+ Op : constant Int32 := Get_Intrinsic_Operation (Stmt);
begin
- Op := Get_Intrinsic_Operation (Stmt);
+ -- Call sym
Gen_Call (Intrinsics_Symbol (Op));
- Start_Insn;
-- addl esp, val
- Gen_B8 (2#100000_11#);
- Gen_B8 (2#11_000_100#);
- Gen_B8 (16);
- End_Insn;
+ Emit_Addl_Sp_Imm (16);
end Emit_Intrinsic;
procedure Emit_Setcc (Dest : O_Enode; Cond : O_Reg) is
begin
pragma Assert (Cond in Regs_Cc);
Start_Insn;
- Gen_B8 (16#0f#);
- Gen_B8 (16#90# + To_Cond (Cond));
+ Gen_B8 (Opc_0f);
+ Gen_B8 (Opc2_0f_Setcc + To_Cond (Cond));
Gen_Rm (2#000_000#, Dest, Sz_8);
End_Insn;
end Emit_Setcc;
@@ -979,8 +1094,8 @@ package body Ortho_Code.X86.Emits is
begin
pragma Assert (Cond in Regs_Cc);
Start_Insn;
- Gen_B8 (16#0f#);
- Gen_B8 (16#90# + To_Cond (Cond));
+ Gen_B8 (Opc_0f);
+ Gen_B8 (Opc2_0f_Setcc + To_Cond (Cond));
Gen_B8 (2#11_000_000# + To_Reg32 (Reg, Sz_8));
End_Insn;
end Emit_Setcc_Reg;
@@ -988,29 +1103,15 @@ package body Ortho_Code.X86.Emits is
procedure Emit_Tst (Reg : O_Reg; Sz : Insn_Size) is
begin
Start_Insn;
- Gen_Insn_Sz (2#1000_0100#, Sz);
+ Gen_Insn_Sz (Opc_Test_Rm_Reg, Sz);
Gen_B8 (2#11_000_000# + To_Reg32 (Reg, Sz) * 9);
End_Insn;
end Emit_Tst;
- procedure Gen_Cmp_Imm (Reg : O_Reg; Val : Int32; Sz : Insn_Size)
- is
- B : Byte;
+ procedure Gen_Cmp_Imm (Reg : O_Reg; Val : Int32; Sz : Insn_Size) is
begin
- Start_Insn;
- if Val <= 127 and Val >= -128 then
- B := 2#10#;
- else
- B := 0;
- end if;
- Gen_Insn_Sz (2#1000_0000# + B, Sz);
- Gen_B8 (2#11_111_000# + To_Reg32 (Reg));
- if B = 0 then
- Gen_Le32 (Unsigned_32 (To_Uns32 (Val)));
- else
- Gen_B8 (Byte (To_Uns32 (Val) and 16#Ff#));
- end if;
- End_Insn;
+ Init_Modrm_Reg (Reg, Sz);
+ Gen_Insn_Grp1 (Opc2_Grp1_Cmp, Sz, Val);
end Gen_Cmp_Imm;
procedure Emit_Spill (Stmt : O_Enode; Sz : Insn_Size)
@@ -1028,7 +1129,7 @@ package body Ortho_Code.X86.Emits is
end if;
end if;
Start_Insn;
- Gen_Insn_Sz (2#1000_1000#, Sz);
+ Gen_Insn_Sz (Opc_Mov_Rm_Reg, Sz);
Gen_Rm (To_Reg32 (Reg, Sz) * 8, Stmt, Sz);
End_Insn;
end Emit_Spill;
@@ -1037,24 +1138,25 @@ package body Ortho_Code.X86.Emits is
is
begin
Start_Insn;
- Gen_Insn_Sz (2#1000_1010#, Sz);
+ Gen_Insn_Sz (Opc_Mov_Reg_Rm, Sz);
Gen_Rm (To_Reg32 (Reg, Sz) * 8, Val, Sz);
End_Insn;
end Emit_Load;
procedure Emit_Lea (Stmt : O_Enode)
is
- Reg : O_Reg;
+ Reg : constant O_Reg := Get_Expr_Reg (Stmt);
begin
-- Hack: change the register to use the real address instead of it.
- Reg := Get_Expr_Reg (Stmt);
Set_Expr_Reg (Stmt, R_Mem);
- Start_Insn;
- Gen_B8 (2#10001101#);
Init_Rm_Mem (Stmt, Sz_32l);
- Gen_Rm_Mem (To_Reg32 (Reg) * 8);
+ Start_Insn;
+ Gen_B8 (Opc_Leal_Reg_Rm);
+ Gen_Mod_Rm (To_Reg32 (Reg) * 8);
End_Insn;
+
+ -- Restore.
Set_Expr_Reg (Stmt, Reg);
end Emit_Lea;
@@ -1063,46 +1165,41 @@ package body Ortho_Code.X86.Emits is
begin
pragma Assert (Get_Expr_Reg (Get_Expr_Left (Stmt)) = R_Ax);
Start_Insn;
- Gen_Insn_Sz (16#F6#, Sz);
- Gen_Rm (2#100_000#, Get_Expr_Right (Stmt), Sz);
+ Gen_Insn_Sz (Opc_Grp3_Width, Sz);
+ Gen_Rm (Opc2_Grp3_Mul, Get_Expr_Right (Stmt), Sz);
End_Insn;
end Gen_Umul;
procedure Gen_Mul (Stmt : O_Enode; Sz : Insn_Size)
is
- Reg : O_Reg;
- Right : O_Enode;
+ Reg : constant O_Reg := Get_Expr_Reg (Stmt);
+ Right : constant O_Enode := Get_Expr_Right (Stmt);
Reg_R : O_Reg;
begin
- Reg := Get_Expr_Reg (Stmt);
- Right := Get_Expr_Right (Stmt);
- if Get_Expr_Reg (Get_Expr_Left (Stmt)) /= Reg
- or Sz /= Sz_32l
- then
- raise Program_Error;
- end if;
+ pragma Assert (Get_Expr_Reg (Get_Expr_Left (Stmt)) = Reg);
+ pragma Assert (Sz = Sz_32l);
Start_Insn;
if Reg = R_Ax then
- Gen_Insn_Sz (16#F6#, Sz);
- Gen_Rm (2#100_000#, Right, Sz);
+ Gen_Insn_Sz (Opc_Grp3_Width, Sz);
+ Gen_Rm (Opc2_Grp3_Mul, Right, Sz);
else
Reg_R := Get_Expr_Reg (Right);
case Reg_R is
when R_Imm =>
if Is_Imm8 (Right, Sz) then
- Gen_B8 (16#6B#);
+ Gen_B8 (Opc_Imul_Reg_Rm_Imm8);
Gen_B8 (To_Reg32 (Reg, Sz) * 9 or 2#11_000_000#);
Gen_Imm8 (Right, Sz);
else
- Gen_B8 (16#69#);
+ Gen_B8 (Opc_Imul_Reg_Rm_Imm32);
Gen_B8 (To_Reg32 (Reg, Sz) * 9 or 2#11_000_000#);
Gen_Imm (Right, Sz);
end if;
when R_Mem
| R_Spill
| Regs_R32 =>
- Gen_B8 (16#0F#);
- Gen_B8 (16#AF#);
+ Gen_B8 (Opc_0f);
+ Gen_B8 (Opc2_0f_Imul);
Gen_Rm (To_Reg32 (Reg, Sz) * 8, Right, Sz);
when others =>
Error_Emit ("gen_mul", Stmt);
@@ -1115,15 +1212,9 @@ package body Ortho_Code.X86.Emits is
procedure Gen_Ov_Check (Cond : O_Reg) is
begin
-- JXX +2
- Start_Insn;
- Gen_B8 (16#70# + To_Cond (Cond));
- Gen_B8 (16#02#);
- End_Insn;
+ Gen_2 (Opc_Jcc + To_Cond (Cond), 16#02#);
-- INT 4 (overflow).
- Start_Insn;
- Gen_B8 (16#CD#);
- Gen_B8 (16#04#);
- End_Insn;
+ Gen_2 (Opc_Int, 16#04#);
end Gen_Ov_Check;
procedure Emit_Abs (Val : O_Enode; Mode : Mode_Type)
@@ -1142,22 +1233,19 @@ package body Ortho_Code.X86.Emits is
Emit_Tst (Get_Expr_Reg (Val), Szh);
-- JXX +
Start_Insn;
- Gen_B8 (16#70# + To_Cond (R_Sge));
+ Gen_B8 (Opc_Jcc + To_Cond (R_Sge));
Gen_B8 (0);
End_Insn;
Pc_Jmp := Get_Current_Pc;
-- NEG
- Gen_Mono_Op (2#011_000#, Val, Sz_32l);
+ Gen_Grp3_Insn (Opc2_Grp3_Neg, Val, Sz_32l);
if Mode = Mode_I64 then
- -- Propagate carray.
+ -- Propagate carry.
-- Adc reg,0
-- neg reg
- Start_Insn;
- Gen_B8 (2#100000_11#);
- Gen_Rm (2#010_000#, Val, Sz_32h);
- Gen_B8 (0);
- End_Insn;
- Gen_Mono_Op (2#011_000#, Val, Sz_32h);
+ Init_Rm_Expr (Val, Sz_32h);
+ Gen_Insn_Grp1 (Opc2_Grp1_Adc, Sz_32h, 0);
+ Gen_Grp3_Insn (Opc2_Grp3_Neg, Val, Sz_32h);
end if;
Gen_Into;
Patch_B8 (Pc_Jmp - 1, Unsigned_8 (Get_Current_Pc - Pc_Jmp));
@@ -1165,39 +1253,31 @@ package body Ortho_Code.X86.Emits is
procedure Gen_Alloca (Stmt : O_Enode)
is
- Reg : O_Reg;
+ Reg : constant O_Reg := Get_Expr_Reg (Get_Expr_Operand (Stmt));
begin
- Reg := Get_Expr_Reg (Get_Expr_Operand (Stmt));
- if Reg not in Regs_R32 or else Reg /= Get_Expr_Reg (Stmt) then
- raise Program_Error;
- end if;
+ pragma Assert (Reg in Regs_R32);
+ pragma Assert (Reg = Get_Expr_Reg (Stmt));
-- Align stack on word.
-- Add reg, (stack_boundary - 1)
Start_Insn;
- Gen_B8 (2#1000_0011#);
- Gen_B8 (2#11_000_000# + To_Reg32 (Reg));
+ Gen_B8 (Opc_Grp1v_Rm_Imm8);
+ Gen_B8 (Opc2_Grp1_Add or 2#11_000_000# or To_Reg32 (Reg));
Gen_B8 (Byte (X86.Flags.Stack_Boundary - 1));
End_Insn;
-- and reg, ~(stack_boundary - 1)
Start_Insn;
- Gen_B8 (2#1000_0001#);
- Gen_B8 (2#11_100_000# + To_Reg32 (Reg));
+ Gen_B8 (Opc_Grp1v_Rm_Imm32);
+ Gen_B8 (Opc2_Grp1_And or 2#11_000_000# or To_Reg32 (Reg));
Gen_Le32 (not (X86.Flags.Stack_Boundary - 1));
End_Insn;
if X86.Flags.Flag_Alloca_Call then
Gen_Call (Chkstk_Symbol);
else
-- subl esp, reg
- Start_Insn;
- Gen_B8 (2#0001_1011#);
- Gen_B8 (2#11_100_000# + To_Reg32 (Reg));
- End_Insn;
+ Gen_2 (Opc_Subl_Reg_Rm, 2#11_100_000# + To_Reg32 (Reg));
end if;
-- movl reg, esp
- Start_Insn;
- Gen_B8 (2#1000_1001#);
- Gen_B8 (2#11_100_000# + To_Reg32 (Reg));
- End_Insn;
+ Gen_2 (Opc_Mov_Rm_Reg + 1, 2#11_100_000# + To_Reg32 (Reg));
end Gen_Alloca;
-- Byte/word to long.
@@ -1206,7 +1286,7 @@ package body Ortho_Code.X86.Emits is
B : Byte;
begin
Start_Insn;
- Gen_B8 (16#0f#);
+ Gen_B8 (Opc_0f);
case Sz is
when Sz_8 =>
B := 0;
@@ -1216,7 +1296,7 @@ package body Ortho_Code.X86.Emits is
| Sz_32h =>
raise Program_Error;
end case;
- Gen_B8 (2#1011_0110# + B);
+ Gen_B8 (Opc2_0f_Movzx + B);
Gen_Rm (To_Reg32 (Reg) * 8, Op, Sz_8);
End_Insn;
end Gen_Movzx;
@@ -1249,8 +1329,8 @@ package body Ortho_Code.X86.Emits is
end if;
-- cmpl VAL, 0xff
Start_Insn;
- Gen_B8 (2#1000_0001#);
- Gen_Rm (2#111_000#, Op, Sz_32l);
+ Gen_B8 (Opc_Grp1v_Rm_Imm32);
+ Gen_Rm (Opc2_Grp1_Cmp, Op, Sz_32l);
Gen_Le32 (16#00_00_00_Ff#);
End_Insn;
Gen_Ov_Check (R_Ule);
@@ -1299,11 +1379,7 @@ package body Ortho_Code.X86.Emits is
Gen_B8 (2#00_100_100#);
End_Insn;
-- addl %esp, 4
- Start_Insn;
- Gen_B8 (2#100000_11#);
- Gen_B8 (2#11_000_100#);
- Gen_B8 (4);
- End_Insn;
+ Emit_Addl_Sp_Imm (4);
when others =>
Error_Emit ("gen_conv_i32", Stmt);
end case;
@@ -1373,14 +1449,14 @@ package body Ortho_Code.X86.Emits is
pragma Assert (Reg_Res = R_Ax);
-- move dx to reg_helper
Start_Insn;
- Gen_B8 (2#1000_1001#);
+ Gen_B8 (Opc_Mov_Rm_Reg + 1);
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 (Opc_Cmpl_Rm_Reg);
Gen_B8 (2#11_010_000# + To_Reg32 (Reg_Helper));
End_Insn;
-- Overflow if extended value is different from initial value.
@@ -1417,11 +1493,7 @@ package body Ortho_Code.X86.Emits is
Gen_B8 (2#00_100_100#);
End_Insn;
-- addl %esp, 8
- Start_Insn;
- Gen_B8 (2#100000_11#);
- Gen_B8 (2#11_000_100#);
- Gen_B8 (8);
- End_Insn;
+ Emit_Addl_Sp_Imm (8);
when others =>
Error_Emit ("gen_conv_I64", Stmt);
end case;
@@ -1433,11 +1505,7 @@ package body Ortho_Code.X86.Emits is
case Get_Expr_Mode (Stmt) is
when Mode_I32 =>
-- subl %esp, 4
- Start_Insn;
- Gen_B8 (2#100000_11#);
- Gen_B8 (2#11_101_100#);
- Gen_B8 (4);
- End_Insn;
+ Emit_Subl_Sp_Imm (4);
-- fistp (%esp)
Start_Insn;
Gen_B8 (2#11011_011#);
@@ -1447,11 +1515,7 @@ package body Ortho_Code.X86.Emits is
Emit_Pop_32 (Stmt, Sz_32l);
when Mode_I64 =>
-- subl %esp, 8
- Start_Insn;
- Gen_B8 (2#100000_11#);
- Gen_B8 (2#11_101_100#);
- Gen_B8 (8);
- End_Insn;
+ Emit_Subl_Sp_Imm (8);
-- fistp (%esp)
Start_Insn;
Gen_B8 (2#11011_111#);
@@ -1465,25 +1529,25 @@ package body Ortho_Code.X86.Emits is
end case;
end Gen_Conv_Fp;
- procedure Gen_Emit_Op (Stmt : O_Enode; Cl : Byte; Ch : Byte) is
+ procedure Gen_Grp1_Insn_Mode (Stmt : O_Enode; Cl : Byte; Ch : Byte) is
begin
case Get_Expr_Mode (Stmt) is
when Mode_U32
| Mode_I32
| Mode_P32 =>
- Emit_Op (Cl, Stmt, Sz_32l);
+ Gen_Grp1_Insn (Cl, Stmt, Sz_32l);
when Mode_I64
| Mode_U64 =>
- Emit_Op (Cl, Stmt, Sz_32l);
- Emit_Op (Ch, Stmt, Sz_32h);
+ Gen_Grp1_Insn (Cl, Stmt, Sz_32l);
+ Gen_Grp1_Insn (Ch, Stmt, Sz_32h);
when Mode_B2
| Mode_I8
| Mode_U8 =>
- Emit_Op (Cl, Stmt, Sz_8);
+ Gen_Grp1_Insn (Cl, Stmt, Sz_8);
when others =>
- Error_Emit ("gen_emit_op", Stmt);
+ Error_Emit ("gen_grp1_insn_mode", Stmt);
end case;
- end Gen_Emit_Op;
+ end Gen_Grp1_Insn_Mode;
procedure Gen_Check_Overflow (Mode : Mode_Type) is
begin
@@ -1528,7 +1592,7 @@ package body Ortho_Code.X86.Emits is
end case;
Gen_B8 (2#11011_000# or B_Size);
Init_Rm_Mem (Right, Sz_32l);
- Gen_Rm_Mem (B_Mem);
+ Gen_Mod_Rm (B_Mem);
when others =>
raise Program_Error;
end case;
@@ -1573,41 +1637,29 @@ package body Ortho_Code.X86.Emits is
Emit_Load (R_Dx, Right, Sz_32l);
-- xorl %eax -> %edx
Start_Insn;
- Gen_B8 (2#0011_0011#);
- Gen_B8 (2#11_010_000#);
+ Gen_B8 (Opc_Xorl_Rm_Reg);
+ Gen_B8 (2#11_000_010#);
End_Insn;
Gen_Cdq;
-- js
- Start_Insn;
- Gen_B8 (2#0111_1000#);
- Gen_B8 (0);
- End_Insn;
+ Gen_2 (Opc_Jcc + 2#1000#, 0);
Pc1 := Get_Current_Pc;
-- idiv
- Gen_Mono_Op (2#111_000#, Right, Sz_32l);
+ Gen_Grp3_Insn (Opc2_Grp3_Idiv, Right, Sz_32l);
-- jmp
- Start_Insn;
- Gen_B8 (2#1110_1011#);
- Gen_B8 (0);
- End_Insn;
+ Gen_2 (Opc_Jmp_Short, 0);
Pc2 := Get_Current_Pc;
Patch_B8 (Pc1 - 1, Unsigned_8 (Get_Current_Pc - Pc1));
-- idiv
- Gen_Mono_Op (2#111_000#, Right, Sz_32l);
+ Gen_Grp3_Insn (Opc2_Grp3_Idiv, Right, Sz_32l);
-- tstl %edx,%edx
- Start_Insn;
- Gen_B8 (2#1000_0101#);
- Gen_B8 (2#11_010_010#);
- End_Insn;
+ Gen_2 (Opc_Test_Rm_Reg + 1, 2#11_010_010#);
-- jz
- Start_Insn;
- Gen_B8 (2#0111_0100#);
- Gen_B8 (0);
- End_Insn;
+ Gen_2 (Opc_Jcc + 2#0100#, 0);
Pc3 := Get_Current_Pc;
-- addl b, %edx
Start_Insn;
- Gen_B8 (2#00_000_011#);
+ Gen_B8 (Opc_Addl_Reg_Rm);
Gen_Rm (2#010_000#, Right, Sz_32l);
End_Insn;
Patch_B8 (Pc2 - 1, Unsigned_8 (Get_Current_Pc - Pc2));
@@ -1640,20 +1692,20 @@ package body Ortho_Code.X86.Emits is
if Mode in Mode_Fp then
Gen_Emit_Fp_Or_Xmm_Op (Stmt, 2#000_000#, 2#000_000#, 16#58#);
else
- Gen_Emit_Op (Stmt, 2#000_000#, 2#010_000#);
+ Gen_Grp1_Insn_Mode (Stmt, Opc2_Grp1_Add, Opc2_Grp1_Adc);
Gen_Check_Overflow (Mode);
end if;
when OE_Or =>
- Gen_Emit_Op (Stmt, 2#001_000#, 2#001_000#);
+ Gen_Grp1_Insn_Mode (Stmt, Opc2_Grp1_Or, Opc2_Grp1_Or);
when OE_And =>
- Gen_Emit_Op (Stmt, 2#100_000#, 2#100_000#);
+ Gen_Grp1_Insn_Mode (Stmt, Opc2_Grp1_And, Opc2_Grp1_And);
when OE_Xor =>
- Gen_Emit_Op (Stmt, 2#110_000#, 2#110_000#);
+ Gen_Grp1_Insn_Mode (Stmt, Opc2_Grp1_Xor, Opc2_Grp1_Xor);
when OE_Sub_Ov =>
if Mode in Mode_Fp then
Gen_Emit_Fp_Or_Xmm_Op (Stmt, 2#100_000#, 2#100_000#, 16#5c#);
else
- Gen_Emit_Op (Stmt, 2#101_000#, 2#011_000#);
+ Gen_Grp1_Insn_Mode (Stmt, Opc2_Grp1_Sub, Opc2_Grp1_Sbb);
Gen_Check_Overflow (Mode);
end if;
when OE_Mul_Ov
@@ -1666,7 +1718,8 @@ package body Ortho_Code.X86.Emits is
when Mode_U32 =>
Gen_Mul (Stmt, Sz_32l);
when Mode_I32 =>
- Gen_Mono_Op (2#101_000#, Get_Expr_Right (Stmt), Sz_32l);
+ Gen_Grp3_Insn (Opc2_Grp3_Imul,
+ Get_Expr_Right (Stmt), Sz_32l);
when Mode_F32
| Mode_F64 =>
Gen_Emit_Fp_Or_Xmm_Op (Stmt, 2#001_000#, 2#001_000#, 16#59#);
@@ -1699,9 +1752,7 @@ package body Ortho_Code.X86.Emits is
end if;
End_Insn;
else
- if Get_Expr_Reg (Right) /= R_Cx then
- raise Program_Error;
- end if;
+ pragma Assert (Get_Expr_Reg (Right) = R_Cx);
Start_Insn;
Gen_Insn_Sz (2#1101001_0#, Sz);
Gen_Rm (2#100_000#, Get_Expr_Left (Stmt), Sz);
@@ -1714,22 +1765,21 @@ package body Ortho_Code.X86.Emits is
case Mode is
when Mode_U32 =>
Gen_Clear_Edx;
- Gen_Mono_Op (2#110_000#, Get_Expr_Right (Stmt), Sz_32l);
+ Gen_Grp3_Insn (Opc2_Grp3_Div, Get_Expr_Right (Stmt), Sz_32l);
when Mode_I32 =>
if Kind = OE_Mod then
Emit_Mod (Stmt);
else
Gen_Cdq;
- Gen_Mono_Op (2#111_000#, Get_Expr_Right (Stmt), Sz_32l);
+ Gen_Grp3_Insn
+ (Opc2_Grp3_Idiv, Get_Expr_Right (Stmt), Sz_32l);
end if;
when Mode_F32
| Mode_F64 =>
- if Kind = OE_Div_Ov then
- Gen_Emit_Fp_Or_Xmm_Op
- (Stmt, 2#111_000#, 2#110_000#, 16#5e#);
- else
- raise Program_Error;
- end if;
+ -- No Mod or Rem for fp types.
+ pragma Assert (Kind = OE_Div_Ov);
+ Gen_Emit_Fp_Or_Xmm_Op
+ (Stmt, 2#111_000#, 2#110_000#, 16#5e#);
when others =>
Error_Emit ("emit_insn: mod_ov", Stmt);
end case;
@@ -1739,19 +1789,19 @@ package body Ortho_Code.X86.Emits is
when Mode_B2 =>
-- Xor VAL, $1
Start_Insn;
- Gen_B8 (2#1000_0011#);
- Gen_Rm (2#110_000#, Stmt, Sz_8);
+ Gen_B8 (Opc_Grp1v_Rm_Imm8);
+ Gen_Rm (Opc2_Grp1_Xor, Stmt, Sz_8);
Gen_B8 (16#01#);
End_Insn;
when Mode_U8 =>
- Emit_Mono_Op_Stmt (2#010_000#, Stmt, Sz_8);
+ Gen_Grp3_Insn_Stmt (Opc2_Grp3_Not, Stmt, Sz_8);
when Mode_U16 =>
- Emit_Mono_Op_Stmt (2#010_000#, Stmt, Sz_16);
+ Gen_Grp3_Insn_Stmt (Opc2_Grp3_Not, Stmt, Sz_16);
when Mode_U32 =>
- Emit_Mono_Op_Stmt (2#010_000#, Stmt, Sz_32l);
+ Gen_Grp3_Insn_Stmt (Opc2_Grp3_Not, Stmt, Sz_32l);
when Mode_U64 =>
- Emit_Mono_Op_Stmt (2#010_000#, Stmt, Sz_32l);
- Emit_Mono_Op_Stmt (2#010_000#, Stmt, Sz_32h);
+ Gen_Grp3_Insn_Stmt (Opc2_Grp3_Not, Stmt, Sz_32l);
+ Gen_Grp3_Insn_Stmt (Opc2_Grp3_Not, Stmt, Sz_32h);
when others =>
Error_Emit ("emit_insn: not", Stmt);
end case;
@@ -1759,23 +1809,23 @@ package body Ortho_Code.X86.Emits is
when OE_Neg_Ov =>
case Mode is
when Mode_I8 =>
- Emit_Mono_Op_Stmt (2#011_000#, Stmt, Sz_8);
+ Gen_Grp3_Insn_Stmt (Opc2_Grp3_Neg, Stmt, Sz_8);
--Gen_Into;
when Mode_I16 =>
- Emit_Mono_Op_Stmt (2#011_000#, Stmt, Sz_16);
+ Gen_Grp3_Insn_Stmt (Opc2_Grp3_Neg, Stmt, Sz_16);
--Gen_Into;
when Mode_I32 =>
- Emit_Mono_Op_Stmt (2#011_000#, Stmt, Sz_32l);
+ Gen_Grp3_Insn_Stmt (Opc2_Grp3_Neg, Stmt, Sz_32l);
--Gen_Into;
when Mode_I64 =>
- Emit_Mono_Op_Stmt (2#011_000#, Stmt, Sz_32l);
+ Gen_Grp3_Insn_Stmt (Opc2_Grp3_Neg, Stmt, Sz_32l);
-- adcl 0, high
Start_Insn;
- Gen_B8 (2#100000_11#);
- Gen_Rm (2#010_000#, Get_Expr_Operand (Stmt), Sz_32h);
+ Gen_B8 (Opc_Grp1v_Rm_Imm8);
+ Gen_Rm (Opc2_Grp1_Adc, Get_Expr_Operand (Stmt), Sz_32h);
Gen_B8 (0);
End_Insn;
- Emit_Mono_Op_Stmt (2#011_000#, Stmt, Sz_32h);
+ Gen_Grp3_Insn_Stmt (Opc2_Grp3_Neg, Stmt, Sz_32h);
--Gen_Into;
when Mode_F32
| Mode_F64 =>
@@ -1804,10 +1854,7 @@ package body Ortho_Code.X86.Emits is
when Mode_F32
| Mode_F64 =>
-- fabs
- Start_Insn;
- Gen_B8 (2#11011_001#);
- Gen_B8 (2#1110_0001#);
- End_Insn;
+ Gen_2 (2#11011_001#, 2#1110_0001#);
when others =>
Error_Emit ("emit_insn: abs_ov", Stmt);
end case;
@@ -1817,23 +1864,23 @@ package body Ortho_Code.X86.Emits is
when Mode_U32
| Mode_I32
| Mode_P32 =>
- Emit_Op (2#111_000#, Stmt, Sz_32l);
+ Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_32l);
when Mode_B2
| Mode_I8
| Mode_U8 =>
- Emit_Op (2#111_000#, Stmt, Sz_8);
+ Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_8);
when Mode_U64 =>
declare
Pc : Pc_Type;
begin
- Emit_Op (2#111_000#, Stmt, Sz_32h);
+ Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_32h);
-- jne
Start_Insn;
- Gen_B8 (2#0111_0101#);
+ Gen_B8 (Opc_Jcc + 2#0101#);
Gen_B8 (0);
End_Insn;
Pc := Get_Current_Pc;
- Emit_Op (2#111_000#, Stmt, Sz_32l);
+ Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_32l);
Patch_B8 (Pc - 1, Unsigned_8 (Get_Current_Pc - Pc));
end;
when Mode_I64 =>
@@ -1841,17 +1888,17 @@ package body Ortho_Code.X86.Emits is
Pc : Pc_Type;
begin
Reg := Get_Expr_Reg (Stmt);
- Emit_Op (2#111_000#, Stmt, Sz_32h);
+ 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));
-- jne
Start_Insn;
- Gen_B8 (2#0111_0101#);
+ Gen_B8 (Opc_Jcc + 2#0101#);
Gen_B8 (0);
End_Insn;
Pc := Get_Current_Pc;
- Emit_Op (2#111_000#, Stmt, Sz_32l);
+ Gen_Grp1_Insn (Opc2_Grp1_Cmp, Stmt, Sz_32l);
Emit_Setcc_Reg (Reg, Ekind_Unsigned_To_Cc (Kind));
Patch_B8 (Pc - 1, Unsigned_8 (Get_Current_Pc - Pc));
return;
@@ -2021,7 +2068,7 @@ package body Ortho_Code.X86.Emits is
| Mode_I32 =>
-- mov REG, OP
Start_Insn;
- Gen_Insn_Sz (2#1000_101_0#, Sz_32l);
+ Gen_Insn_Sz (Opc_Mov_Reg_Rm, Sz_32l);
Gen_Rm (To_Reg32 (Reg, Sz_32l) * 8, Operand, Sz_32l);
End_Insn;
when others =>
@@ -2111,9 +2158,7 @@ package body Ortho_Code.X86.Emits is
use Ortho_Code.X86.Insns;
begin
if Reg_Used (Reg) then
- Start_Insn;
- Gen_B8 (2#01010_000# + To_Reg32 (Reg, Sz_32l));
- End_Insn;
+ Gen_1 (Opc_Push_Reg + To_Reg32 (Reg, Sz_32l));
end if;
end Push_Reg_If_Used;
@@ -2122,9 +2167,7 @@ package body Ortho_Code.X86.Emits is
use Ortho_Code.X86.Insns;
begin
if Reg_Used (Reg) then
- Start_Insn;
- Gen_B8 (2#01011_000# + To_Reg32 (Reg, Sz_32l));
- End_Insn;
+ Gen_1 (Opc_Pop_Reg + To_Reg32 (Reg, Sz_32l));
end if;
end Pop_Reg_If_Used;
@@ -2157,9 +2200,9 @@ package body Ortho_Code.X86.Emits is
Set_Symbol_Pc (Sym, Is_Global);
Subprg_Pc := Get_Current_Pc;
- Saved_Regs_Size := Boolean'Pos(Reg_Used (R_Di)) * 4
- + Boolean'Pos(Reg_Used (R_Si)) * 4
- + Boolean'Pos(Reg_Used (R_Bx)) * 4;
+ Saved_Regs_Size := Boolean'Pos (Reg_Used (R_Di)) * 4
+ + Boolean'Pos (Reg_Used (R_Si)) * 4
+ + Boolean'Pos (Reg_Used (R_Bx)) * 4;
-- Compute frame size.
-- 8 bytes are used by return address and saved frame pointer.
@@ -2172,12 +2215,10 @@ package body Ortho_Code.X86.Emits is
-- Emit prolog.
-- push %ebp
- Start_Insn;
- Gen_B8 (2#01010_101#);
- End_Insn;
+ Gen_1 (Opc_Push_Reg + To_Reg32 (R_Bp));
-- movl %esp, %ebp
Start_Insn;
- Gen_B8 (2#1000100_1#);
+ Gen_B8 (Opc_Mov_Rm_Reg + 1);
Gen_B8 (2#11_100_101#);
End_Insn;
-- subl XXX, %esp
@@ -2185,21 +2226,12 @@ package body Ortho_Code.X86.Emits is
if not X86.Flags.Flag_Alloca_Call
or else Frame_Size <= 4096
then
- Start_Insn;
- if Frame_Size < 128 then
- Gen_B8 (2#100000_11#);
- Gen_B8 (2#11_101_100#);
- Gen_B8 (Byte (Frame_Size));
- else
- Gen_B8 (2#100000_01#);
- Gen_B8 (2#11_101_100#);
- Gen_Le32 (Frame_Size);
- end if;
- End_Insn;
+ Init_Modrm_Reg (R_Sp, Sz_32l);
+ Gen_Insn_Grp1 (Opc2_Grp1_Sub, Sz_32l, Int32 (Frame_Size));
else
-- mov stack_size,%eax
Start_Insn;
- Gen_B8 (2#1011_1_000#);
+ Gen_B8 (Opc_Movl_Imm_Reg + To_Reg32 (R_Ax));
Gen_Le32 (Frame_Size);
End_Insn;
Gen_Call (Chkstk_Symbol);
@@ -2235,8 +2267,8 @@ package body Ortho_Code.X86.Emits is
| Mode_B2 =>
-- movzx %al,%eax
Start_Insn;
- Gen_B8 (16#0f#);
- Gen_B8 (2#1011_0110#);
+ Gen_B8 (Opc_0f);
+ Gen_B8 (Opc2_0f_Movzx);
Gen_B8 (2#11_000_000#);
End_Insn;
when Mode_U32
@@ -2252,15 +2284,9 @@ package body Ortho_Code.X86.Emits is
end case;
end if;
- -- leave
- Start_Insn;
- Gen_B8 (2#1100_1001#);
- End_Insn;
-
- -- ret
- Start_Insn;
- Gen_B8 (2#1100_0011#);
- End_Insn;
+ -- leave; ret;
+ Gen_1 (Opc_Leave);
+ Gen_1 (Opc_Ret);
if Flag_Debug = Debug_Dwarf then
Set_Body_Info (Subprg.D_Body, Int32 (Get_Current_Pc - Subprg_Pc));