From 8b20df13007f67f5c25a9801e917ae4feea0826b Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Mon, 9 Nov 2015 08:03:22 +0100 Subject: Rewrite of ortho_code-x86-emits. --- src/ortho/mcode/ortho_code-x86-emits.adb | 658 ++++++++++++++++--------------- 1 file changed, 342 insertions(+), 316 deletions(-) (limited to 'src') 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)); -- cgit