aboutsummaryrefslogtreecommitdiffstats
path: root/ortho/mcode/disa_x86.adb
diff options
context:
space:
mode:
Diffstat (limited to 'ortho/mcode/disa_x86.adb')
-rw-r--r--ortho/mcode/disa_x86.adb997
1 files changed, 0 insertions, 997 deletions
diff --git a/ortho/mcode/disa_x86.adb b/ortho/mcode/disa_x86.adb
deleted file mode 100644
index 1d2d48565..000000000
--- a/ortho/mcode/disa_x86.adb
+++ /dev/null
@@ -1,997 +0,0 @@
--- X86 disassembler.
--- Copyright (C) 2006 Tristan Gingold
---
--- GHDL is free software; you can redistribute it and/or modify it under
--- the terms of the GNU General Public License as published by the Free
--- Software Foundation; either version 2, or (at your option) any later
--- version.
---
--- GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
--- WARRANTY; without even the implied warranty of MERCHANTABILITY or
--- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
--- for more details.
---
--- You should have received a copy of the GNU General Public License
--- along with GCC; see the file COPYING. If not, write to the Free
--- Software Foundation, 59 Temple Place - Suite 330, Boston, MA
--- 02111-1307, USA.
-with System.Address_To_Access_Conversions;
-
-package body Disa_X86 is
- type Byte is new Interfaces.Unsigned_8;
- type Bf_2 is mod 2 ** 2;
- type Bf_3 is mod 2 ** 3;
- type Byte_Vector is array (Natural) of Byte;
- package Bv_Addr2acc is new System.Address_To_Access_Conversions
- (Object => Byte_Vector);
- use Bv_Addr2acc;
-
- type Cstring_Acc is access constant String;
- type Index_Type is
- (
- N_None,
- N_Push,
- N_Pop,
- N_Ret,
- N_Mov,
- N_Add,
- N_Or,
- N_Adc,
- N_Sbb,
- N_And,
- N_Sub,
- N_Xor,
- N_Cmp,
- N_Into,
- N_Jmp,
- N_Jcc,
- N_Setcc,
- N_Call,
- N_Int,
- N_Cdq,
- N_Imul,
- N_Mul,
- N_Leave,
- N_Test,
- N_Lea,
- N_O,
- N_No,
- N_B,
- N_AE,
- N_E,
- N_Ne,
- N_Be,
- N_A,
- N_S,
- N_Ns,
- N_P,
- N_Np,
- N_L,
- N_Ge,
- N_Le,
- N_G,
- N_Not,
- N_Neg,
- N_Cbw,
- N_Div,
- N_Idiv,
- N_Movsx,
- N_Movzx,
- N_Nop,
- N_Hlt,
- N_Inc,
- N_Dec,
- N_Rol,
- N_Ror,
- N_Rcl,
- N_Rcr,
- N_Shl,
- N_Shr,
- N_Sar,
- N_Fadd,
- N_Fmul,
- N_Fcom,
- N_Fcomp,
- N_Fsub,
- N_Fsubr,
- N_Fdiv,
- N_Fdivr,
-
- G_1,
- G_2,
- G_3,
- G_5
- );
-
- type Names_Type is array (Index_Type range <>) of Cstring_Acc;
- subtype S is String;
- Names : constant Names_Type :=
- (N_None => new S'("none"),
- N_Push => new S'("push"),
- N_Pop => new S'("pop"),
- N_Ret => new S'("ret"),
- N_Mov => new S'("mov"),
- N_Add => new S'("add"),
- N_Or => new S'("or"),
- N_Adc => new S'("adc"),
- N_Sbb => new S'("sbb"),
- N_And => new S'("and"),
- N_Sub => new S'("sub"),
- N_Xor => new S'("xor"),
- N_Cmp => new S'("cmp"),
- N_Into => new S'("into"),
- N_Jmp => new S'("jmp"),
- N_Jcc => new S'("j"),
- N_Int => new S'("int"),
- N_Cdq => new S'("cdq"),
- N_Call => new S'("call"),
- N_Imul => new S'("imul"),
- N_Mul => new S'("mul"),
- N_Leave => new S'("leave"),
- N_Test => new S'("test"),
- N_Setcc => new S'("set"),
- N_Lea => new S'("lea"),
- N_O => new S'("o"),
- N_No => new S'("no"),
- N_B => new S'("b"),
- N_AE => new S'("ae"),
- N_E => new S'("e"),
- N_Ne => new S'("ne"),
- N_Be => new S'("be"),
- N_A => new S'("a"),
- N_S => new S'("s"),
- N_Ns => new S'("ns"),
- N_P => new S'("p"),
- N_Np => new S'("np"),
- N_L => new S'("l"),
- N_Ge => new S'("ge"),
- N_Le => new S'("le"),
- N_G => new S'("g"),
- N_Not => new S'("not"),
- N_Neg => new S'("neg"),
- N_Cbw => new S'("cbw"),
- N_Div => new S'("div"),
- N_Idiv => new S'("idiv"),
- N_Movsx => new S'("movsx"),
- N_Movzx => new S'("movzx"),
- N_Nop => new S'("nop"),
- N_Hlt => new S'("hlt"),
- N_Inc => new S'("inc"),
- N_Dec => new S'("dec"),
- N_Rol => new S'("rol"),
- N_Ror => new S'("ror"),
- N_Rcl => new S'("rcl"),
- N_Rcr => new S'("rcr"),
- N_Shl => new S'("shl"),
- N_Shr => new S'("shr"),
- N_Sar => new S'("sar"),
- N_Fadd => new S'("fadd"),
- N_Fmul => new S'("fmul"),
- N_Fcom => new S'("fcom"),
- N_Fcomp => new S'("fcomp"),
- N_Fsub => new S'("fsub"),
- N_Fsubr => new S'("fsubr"),
- N_Fdiv => new S'("fdiv"),
- N_Fdivr => new S'("fdivr")
- );
-
-
-
- -- Format of an instruction.
- -- MODRM_SRC_8 : modrm byte follow, and modrm is source, witdh = 8bits
- -- MODRM_DST_8 : modrm byte follow, and modrm is dest, width = 8 bits.
- -- MODRM_SRC_W : modrm byte follow, and modrm is source, width = 16/32 bits
- -- MODRM_DST_W : modrm byte follow, and modrm is dest, width =16/32 bits.
- -- MODRM_IMM_W : modrm byte follow, with an opcode in the reg field,
- -- followed by an immediat, width = 16/32 bits.
- -- MODRM_IMM_8 : modrm byte follow, with an opcode in the reg field,
- -- followed by an immediat, width = 8 bits.
- -- IMM : the opcode is followed by an immediate value.
- -- PREFIX : the opcode is a prefix (1 byte).
- -- OPCODE : inherent addressing.
- -- OPCODE2 : a second byte specify the instruction.
- -- REG_IMP : register is in the 3 LSB of the opcode.
- -- REG_IMM_W : register is in the 3 LSB of the opcode, followed by an
- -- immediat, width = 16/32 bits.
- -- DISP_W : a wide displacement (16/32 bits).
- -- DISP_8 : short displacement (8 bits).
- -- INVALID : bad opcode.
- type Format_Type is (Modrm_Src, Modrm_Dst,
- Modrm_Imm, Modrm_Imm_S,
- Modrm,
- Modrm_Ax,
- Modrm_Imm8,
- Imm, Imm_S, Imm_8,
- Eax_Imm,
- Prefix, Opcode, Opcode2, Reg_Imp,
- Reg_Imm,
- Imp,
- Disp_W, Disp_8,
- Cond_Disp_W, Cond_Disp_8,
- Cond_Modrm,
- Ax_Off_Src, Ax_Off_Dst,
- Invalid);
-
- type Width_Type is (W_None, W_8, W_16, W_32, W_Data);
-
- -- Description for one instruction.
- type Insn_Desc_Type is record
- -- Name of the operation.
- Name : Index_Type;
-
- -- Width of the instruction.
- -- This is used to add a suffix (b,w,l) to the instruction.
- -- This may also be the size of a data.
- Width : Width_Type;
-
- -- Format of the instruction.
- Format : Format_Type;
- end record;
-
- Desc_Invalid : constant Insn_Desc_Type := (N_None, W_None, Invalid);
-
- type Insn_Desc_Array_Type is array (Byte) of Insn_Desc_Type;
- type Group_Desc_Array_Type is array (Bf_3) of Insn_Desc_Type;
- Insn_Desc : constant Insn_Desc_Array_Type :=
- (
- 2#00_000_000# => (N_Add, W_8, Modrm_Dst),
- 2#00_000_001# => (N_Add, W_Data, Modrm_Dst),
- 2#00_000_010# => (N_Add, W_8, Modrm_Src),
- 2#00_000_011# => (N_Add, W_Data, Modrm_Src),
-
- 2#00_001_000# => (N_Or, W_8, Modrm_Dst),
- 2#00_001_001# => (N_Or, W_Data, Modrm_Dst),
- 2#00_001_010# => (N_Or, W_8, Modrm_Src),
- 2#00_001_011# => (N_Or, W_Data, Modrm_Src),
-
- 2#00_011_000# => (N_Sbb, W_8, Modrm_Dst),
- 2#00_011_001# => (N_Sbb, W_Data, Modrm_Dst),
- 2#00_011_010# => (N_Sbb, W_8, Modrm_Src),
- 2#00_011_011# => (N_Sbb, W_Data, Modrm_Src),
-
- 2#00_100_000# => (N_And, W_8, Modrm_Dst),
- 2#00_100_001# => (N_And, W_Data, Modrm_Dst),
- 2#00_100_010# => (N_And, W_8, Modrm_Src),
- 2#00_100_011# => (N_And, W_Data, Modrm_Src),
-
- 2#00_101_000# => (N_Sub, W_8, Modrm_Dst),
- 2#00_101_001# => (N_Sub, W_Data, Modrm_Dst),
- 2#00_101_010# => (N_Sub, W_8, Modrm_Src),
- 2#00_101_011# => (N_Sub, W_Data, Modrm_Src),
-
- 2#00_110_000# => (N_Xor, W_8, Modrm_Dst),
- 2#00_110_001# => (N_Xor, W_Data, Modrm_Dst),
- 2#00_110_010# => (N_Xor, W_8, Modrm_Src),
- 2#00_110_011# => (N_Xor, W_Data, Modrm_Src),
-
- 2#00_111_000# => (N_Cmp, W_8, Modrm_Dst),
- 2#00_111_001# => (N_Cmp, W_Data, Modrm_Dst),
- 2#00_111_010# => (N_Cmp, W_8, Modrm_Src),
- 2#00_111_011# => (N_Cmp, W_Data, Modrm_Src),
-
- 2#00_111_100# => (N_Cmp, W_8, Eax_Imm),
- 2#00_111_101# => (N_Cmp, W_Data, Eax_Imm),
-
- 2#0101_0_000# => (N_Push, W_Data, Reg_Imp),
- 2#0101_0_001# => (N_Push, W_Data, Reg_Imp),
- 2#0101_0_010# => (N_Push, W_Data, Reg_Imp),
- 2#0101_0_011# => (N_Push, W_Data, Reg_Imp),
- 2#0101_0_100# => (N_Push, W_Data, Reg_Imp),
- 2#0101_0_101# => (N_Push, W_Data, Reg_Imp),
- 2#0101_0_110# => (N_Push, W_Data, Reg_Imp),
- 2#0101_0_111# => (N_Push, W_Data, Reg_Imp),
-
- 2#0101_1_000# => (N_Pop, W_Data, Reg_Imp),
- 2#0101_1_001# => (N_Pop, W_Data, Reg_Imp),
- 2#0101_1_010# => (N_Pop, W_Data, Reg_Imp),
- 2#0101_1_011# => (N_Pop, W_Data, Reg_Imp),
- 2#0101_1_100# => (N_Pop, W_Data, Reg_Imp),
- 2#0101_1_101# => (N_Pop, W_Data, Reg_Imp),
- 2#0101_1_110# => (N_Pop, W_Data, Reg_Imp),
- 2#0101_1_111# => (N_Pop, W_Data, Reg_Imp),
-
- 2#0110_1000# => (N_Push, W_Data, Imm),
- 2#0110_1010# => (N_Push, W_Data, Imm_S),
-
- 2#0111_0000# => (N_Jcc, W_None, Cond_Disp_8),
- 2#0111_0001# => (N_Jcc, W_None, Cond_Disp_8),
- 2#0111_0010# => (N_Jcc, W_None, Cond_Disp_8),
- 2#0111_0011# => (N_Jcc, W_None, Cond_Disp_8),
- 2#0111_0100# => (N_Jcc, W_None, Cond_Disp_8),
- 2#0111_0101# => (N_Jcc, W_None, Cond_Disp_8),
- 2#0111_0110# => (N_Jcc, W_None, Cond_Disp_8),
- 2#0111_0111# => (N_Jcc, W_None, Cond_Disp_8),
- 2#0111_1000# => (N_Jcc, W_None, Cond_Disp_8),
- 2#0111_1001# => (N_Jcc, W_None, Cond_Disp_8),
- 2#0111_1010# => (N_Jcc, W_None, Cond_Disp_8),
- 2#0111_1011# => (N_Jcc, W_None, Cond_Disp_8),
- 2#0111_1100# => (N_Jcc, W_None, Cond_Disp_8),
- 2#0111_1101# => (N_Jcc, W_None, Cond_Disp_8),
- 2#0111_1110# => (N_Jcc, W_None, Cond_Disp_8),
- 2#0111_1111# => (N_Jcc, W_None, Cond_Disp_8),
-
- 2#1000_0000# => (G_1, W_8, Modrm_Imm),
- 2#1000_0001# => (G_1, W_Data, Modrm_Imm),
- 2#1000_0011# => (G_1, W_Data, Modrm_Imm_S),
-
- 2#1000_0101# => (N_Test, W_Data, Modrm_Src),
- 2#1000_1101# => (N_Lea, W_Data, Modrm_Src),
-
- 2#1000_1010# => (N_Mov, W_8, Modrm_Src),
- 2#1000_1011# => (N_Mov, W_Data, Modrm_Src),
- 2#1000_1000# => (N_Mov, W_8, Modrm_Dst),
- 2#1000_1001# => (N_Mov, W_Data, Modrm_Dst),
-
- 2#1001_0000# => (N_Nop, W_None, Opcode),
- 2#1001_1001# => (N_Cdq, W_Data, Imp),
-
- 2#1010_0000# => (N_Mov, W_8, Ax_Off_Src),
- 2#1010_0001# => (N_Mov, W_Data, Ax_Off_Src),
- 2#1010_0010# => (N_Mov, W_8, Ax_Off_Dst),
- 2#1010_0011# => (N_Mov, W_Data, Ax_Off_Dst),
-
- 2#1011_0000# => (N_Mov, W_8, Reg_Imm),
-
- 2#1011_1000# => (N_Mov, W_Data, Reg_Imm),
- 2#1011_1001# => (N_Mov, W_Data, Reg_Imm),
- 2#1011_1010# => (N_Mov, W_Data, Reg_Imm),
- 2#1011_1011# => (N_Mov, W_Data, Reg_Imm),
- 2#1011_1100# => (N_Mov, W_Data, Reg_Imm),
- 2#1011_1101# => (N_Mov, W_Data, Reg_Imm),
- 2#1011_1110# => (N_Mov, W_Data, Reg_Imm),
- 2#1011_1111# => (N_Mov, W_Data, Reg_Imm),
-
- 2#1100_0000# => (G_2, W_8, Modrm_Imm8),
- 2#1100_0001# => (G_2, W_Data, Modrm_Imm8),
-
- 2#1100_0011# => (N_Ret, W_None, Opcode),
- 2#1100_0110# => (N_Mov, W_8, Modrm_Imm),
- 2#1100_0111# => (N_Mov, W_Data, Modrm_Imm),
- 2#1100_1001# => (N_Leave, W_None, Opcode),
- 2#1100_1101# => (N_Int, W_None, Imm_8),
- 2#1100_1110# => (N_Into, W_None, Opcode),
-
- 2#1110_1000# => (N_Call, W_None, Disp_W),
- 2#1110_1001# => (N_Jmp, W_None, Disp_W),
- 2#1110_1011# => (N_Jmp, W_None, Disp_8),
-
- 2#1111_0100# => (N_Hlt, W_None, Opcode),
-
- 2#1111_0110# => (G_3, W_None, Invalid),
- 2#1111_0111# => (G_3, W_None, Invalid),
-
- 2#1111_1111# => (G_5, W_None, Invalid),
- --2#1111_1111# => (N_Push, W_Data, Modrm),
- others => (N_None, W_None, Invalid));
-
- Insn_Desc_0F : constant Insn_Desc_Array_Type :=
- (2#1000_0000# => (N_Jcc, W_None, Cond_Disp_W),
- 2#1000_0001# => (N_Jcc, W_None, Cond_Disp_W),
- 2#1000_0010# => (N_Jcc, W_None, Cond_Disp_W),
- 2#1000_0011# => (N_Jcc, W_None, Cond_Disp_W),
- 2#1000_0100# => (N_Jcc, W_None, Cond_Disp_W),
- 2#1000_0101# => (N_Jcc, W_None, Cond_Disp_W),
- 2#1000_0110# => (N_Jcc, W_None, Cond_Disp_W),
- 2#1000_0111# => (N_Jcc, W_None, Cond_Disp_W),
- 2#1000_1000# => (N_Jcc, W_None, Cond_Disp_W),
- 2#1000_1001# => (N_Jcc, W_None, Cond_Disp_W),
- 2#1000_1010# => (N_Jcc, W_None, Cond_Disp_W),
- 2#1000_1011# => (N_Jcc, W_None, Cond_Disp_W),
- 2#1000_1100# => (N_Jcc, W_None, Cond_Disp_W),
- 2#1000_1101# => (N_Jcc, W_None, Cond_Disp_W),
- 2#1000_1110# => (N_Jcc, W_None, Cond_Disp_W),
- 2#1000_1111# => (N_Jcc, W_None, Cond_Disp_W),
-
- 2#1001_0000# => (N_Setcc, W_8, Cond_Modrm),
- 2#1001_0001# => (N_Setcc, W_8, Cond_Modrm),
- 2#1001_0010# => (N_Setcc, W_8, Cond_Modrm),
- 2#1001_0011# => (N_Setcc, W_8, Cond_Modrm),
- 2#1001_0100# => (N_Setcc, W_8, Cond_Modrm),
- 2#1001_0101# => (N_Setcc, W_8, Cond_Modrm),
- 2#1001_0110# => (N_Setcc, W_8, Cond_Modrm),
- 2#1001_0111# => (N_Setcc, W_8, Cond_Modrm),
- 2#1001_1000# => (N_Setcc, W_8, Cond_Modrm),
- 2#1001_1001# => (N_Setcc, W_8, Cond_Modrm),
- 2#1001_1010# => (N_Setcc, W_8, Cond_Modrm),
- 2#1001_1011# => (N_Setcc, W_8, Cond_Modrm),
- 2#1001_1100# => (N_Setcc, W_8, Cond_Modrm),
- 2#1001_1101# => (N_Setcc, W_8, Cond_Modrm),
- 2#1001_1110# => (N_Setcc, W_8, Cond_Modrm),
- 2#1001_1111# => (N_Setcc, W_8, Cond_Modrm),
-
- 2#1011_0110# => (N_Movzx, W_Data, Modrm_Dst),
- 2#1011_1110# => (N_Movsx, W_Data, Modrm_Dst),
- others => (N_None, W_None, Invalid));
-
- -- 16#F7#
- Insn_Desc_G3 : constant Group_Desc_Array_Type :=
- (2#000# => (N_Test, W_Data, Reg_Imm),
- 2#010# => (N_Not, W_Data, Modrm_Dst),
- 2#011# => (N_Neg, W_Data, Modrm_Dst),
- 2#100# => (N_Mul, W_Data, Modrm_Ax),
- 2#101# => (N_Imul, W_Data, Modrm_Ax),
- 2#110# => (N_Div, W_Data, Modrm_Ax),
- 2#111# => (N_Idiv, W_Data, Modrm_Ax),
- others => (N_None, W_None, Invalid));
-
- Insn_Desc_G5 : constant Group_Desc_Array_Type :=
- (2#000# => (N_Inc, W_Data, Modrm),
- 2#001# => (N_Dec, W_Data, Modrm),
- 2#010# => (N_Call, W_Data, Modrm),
- --2#011# => (N_Call, W_Data, Modrm_Ax),
- 2#100# => (N_Jmp, W_Data, Modrm),
- --2#101# => (N_Jmp, W_Data, Modrm_Ax),
- 2#110# => (N_Push, W_Data, Modrm_Ax),
- others => (N_None, W_None, Invalid));
-
- type Group_Name_Array_Type is array (Index_Type range G_1 .. G_2, Bf_3)
- of Index_Type;
- Group_Name : constant Group_Name_Array_Type :=
- (
- G_1 => (N_Add, N_Or, N_Adc, N_Sbb, N_And, N_Sub, N_Xor, N_Cmp),
- G_2 => (N_Rol, N_Ror, N_Rcl, N_Rcr, N_Shl, N_Shr, N_None, N_Sar)
- );
-
- -- Standard widths of operations.
- type Width_Array_Type is array (Width_Type) of Character;
- Width_Char : constant Width_Array_Type :=
- (W_None => '-', W_8 => 'b', W_16 => 'w', W_32 => 'l', W_Data => '?');
- type Width_Len_Type is array (Width_Type) of Natural;
- Width_Len : constant Width_Len_Type :=
- (W_None => 0, W_8 => 1, W_16 => 2, W_32 => 4, W_Data => 0);
-
- -- Registers.
--- type Reg_Type is (Reg_Ax, Reg_Bx, Reg_Cx, Reg_Dx,
--- Reg_Bp, Reg_Sp, Reg_Si, Reg_Di,
--- Reg_Al, Reg_Ah, Reg_Bl, Reg_Bh,
--- Reg_Cl, Reg_Ch, Reg_Dl, Reg_Dh);
-
- -- Bits extraction from byte functions.
- -- For a byte, MSB (most significant bit) is bit 7 while
- -- LSB (least significant bit) is bit 0.
-
- -- Extract bits 2, 1 and 0.
- function Ext_210 (B : Byte) return Bf_3;
- pragma Inline (Ext_210);
-
- -- Extract bits 5-3 of byte B.
- function Ext_543 (B : Byte) return Bf_3;
- pragma Inline (Ext_543);
-
- -- Extract bits 7-6 of byte B.
- function Ext_76 (B : Byte) return Bf_2;
- pragma Inline (Ext_76);
-
- function Ext_210 (B : Byte) return Bf_3 is
- begin
- return Bf_3 (B and 2#111#);
- end Ext_210;
-
- function Ext_543 (B : Byte) return Bf_3 is
- begin
- return Bf_3 (Shift_Right (B, 3) and 2#111#);
- end Ext_543;
-
- function Ext_76 (B : Byte) return Bf_2 is
- begin
- return Bf_2 (Shift_Right (B, 6) and 2#11#);
- end Ext_76;
-
- function Ext_Modrm_Mod (B : Byte) return Bf_2 renames Ext_76;
- function Ext_Modrm_Rm (B : Byte) return Bf_3 renames Ext_210;
- function Ext_Modrm_Reg (B : Byte) return Bf_3 renames Ext_543;
- function Ext_Sib_Base (B : Byte) return Bf_3 renames Ext_210;
- function Ext_Sib_Index (B : Byte) return Bf_3 renames Ext_543;
- function Ext_Sib_Scale (B : Byte) return Bf_2 renames Ext_76;
-
- procedure Disassemble_Insn (Addr : System.Address;
- Pc : Unsigned_32;
- Line : in out String;
- Line_Len : out Natural;
- Insn_Len : out Natural;
- Proc_Cb : Symbol_Proc_Type)
- is
- -- Index in LINE of the next character to be written.
- Lo : Natural;
-
- -- Default width.
- W_Default : constant Width_Type := W_32;
-
- -- The instruction memory, 0 based.
- Mem : Bv_Addr2acc.Object_Pointer;
-
- -- Add NAME to the line.
- procedure Add_Name (Name : Index_Type);
- pragma Inline (Add_Name);
-
- -- Add CHAR to the line.
- procedure Add_Char (C : Character);
- pragma Inline (Add_Char);
-
- -- Add STR to the line.
- procedure Add_String (Str : String) is
- begin
- Line (Lo .. Lo + Str'Length - 1) := Str;
- Lo := Lo + Str'Length;
- end Add_String;
-
- -- Add BYTE to the line.
- procedure Add_Byte (V : Byte) is
- type My_Str is array (Natural range 0 .. 15) of Character;
- Hex_Digit : constant My_Str := "0123456789abcdef";
- begin
- Add_Char (Hex_Digit (Natural (Shift_Right (V, 4) and 16#0f#)));
- Add_Char (Hex_Digit (Natural (Shift_Right (V, 0) and 16#0f#)));
- end Add_Byte;
-
- procedure Add_Name (Name : Index_Type) is
- begin
- Add_String (Names (Name).all);
- end Add_Name;
-
- procedure Add_Char (C : Character) is
- begin
- Line (Lo) := C;
- Lo := Lo + 1;
- end Add_Char;
-
- procedure Add_Comma is
- begin
- Add_String (", ");
- end Add_Comma;
-
- procedure Name_Align (Orig : Natural) is
- begin
- Add_Char (' ');
- while Lo - Orig < 8 loop
- Add_Char (' ');
- end loop;
- end Name_Align;
-
- procedure Add_Opcode (Name : Index_Type; Width : Width_Type)
- is
- L : constant Natural := Lo;
- begin
- Add_Name (Name);
- if False and Width /= W_None then
- Add_Char (Width_Char (Width));
- end if;
- Name_Align (L);
- end Add_Opcode;
-
- procedure Add_Cond_Opcode (Name : Index_Type; B : Byte)
- is
- L : constant Natural := Lo;
- begin
- Add_Name (Name);
- Add_Name (Index_Type'Val (Index_Type'Pos (N_O)
- + Byte'Pos (B and 16#0f#)));
- Name_Align (L);
- end Add_Cond_Opcode;
-
- procedure Decode_Reg_Field (F : Bf_3; W : Width_Type) is
- type Reg_Name2_Array is array (Bf_3) of String (1 .. 2);
- type Reg_Name3_Array is array (Bf_3) of String (1 .. 3);
- Regs_8 : constant Reg_Name2_Array :=
- ("al", "cl", "dl", "bl", "ah", "ch", "dh", "bh");
- Regs_16 : constant Reg_Name2_Array :=
- ("ax", "cx", "dx", "bx", "sp", "bp", "si", "di");
- Regs_32 : constant Reg_Name3_Array :=
- ("eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi");
- begin
- Add_Char ('%');
- case W is
- when W_8 =>
- Add_String (Regs_8 (F));
- when W_16 =>
- Add_String (Regs_16 (F));
- when W_32 =>
- Add_String (Regs_32 (F));
- when W_None
- | W_Data =>
- raise Program_Error;
- end case;
- end Decode_Reg_Field;
-
- procedure Decode_Val (Off : Natural; Width : Width_Type)
- is
- begin
- case Width is
- when W_8 =>
- Add_Byte (Mem (Off));
- when W_16 =>
- Add_Byte (Mem (Off + 1));
- Add_Byte (Mem (Off));
- when W_32 =>
- Add_Byte (Mem (Off + 3));
- Add_Byte (Mem (Off + 2));
- Add_Byte (Mem (Off + 1));
- Add_Byte (Mem (Off + 0));
- when W_None
- | W_Data =>
- raise Program_Error;
- end case;
- end Decode_Val;
-
- function Decode_Val (Off : Natural; Width : Width_Type)
- return Unsigned_32
- is
- V : Unsigned_32;
- begin
- case Width is
- when W_8 =>
- V := Unsigned_32 (Mem (Off));
- -- Sign extension.
- if V >= 16#80# then
- V := 16#Ffff_Ff00# or V;
- end if;
- return V;
- when W_16 =>
- return Shift_Left (Unsigned_32 (Mem (Off + 1)), 8)
- or Unsigned_32 (Mem (Off));
- when W_32 =>
- return Shift_Left (Unsigned_32 (Mem (Off + 3)), 24)
- or Shift_Left (Unsigned_32 (Mem (Off + 2)), 16)
- or Shift_Left (Unsigned_32 (Mem (Off + 1)), 8)
- or Shift_Left (Unsigned_32 (Mem (Off + 0)), 0);
- when W_None
- | W_Data =>
- raise Program_Error;
- end case;
- end Decode_Val;
-
- procedure Decode_Imm (Off : in out Natural; Width : Width_Type)
- is
- begin
- Add_String ("$0x");
- Decode_Val (Off, Width);
- Off := Off + Width_Len (Width);
- end Decode_Imm;
-
- procedure Decode_Disp (Off : in out Natural;
- Width : Width_Type;
- Offset : Unsigned_32 := 0)
- is
- L : Natural;
- V : Unsigned_32;
- Off_Orig : constant Natural := Off;
- begin
- L := Lo;
- V := Decode_Val (Off, Width) + Offset;
- Off := Off + Width_Len (Width);
- if Proc_Cb /= null then
- Proc_Cb.all (Mem (Off)'Address,
- Line (Lo .. Line'Last), Lo);
- end if;
- if L /= Lo then
- if V = 0 then
- return;
- end if;
- Add_String (" + ");
- end if;
- Add_String ("0x");
- if Offset = 0 then
- Decode_Val (Off_Orig, Width);
- else
- Add_Byte (Byte (Shift_Right (V, 24) and 16#Ff#));
- Add_Byte (Byte (Shift_Right (V, 16) and 16#Ff#));
- Add_Byte (Byte (Shift_Right (V, 8) and 16#Ff#));
- Add_Byte (Byte (Shift_Right (V, 0) and 16#Ff#));
- end if;
- end Decode_Disp;
-
- procedure Decode_Modrm_Reg (B : Byte; Width : Width_Type) is
- begin
- Decode_Reg_Field (Ext_Modrm_Reg (B), Width);
- end Decode_Modrm_Reg;
-
- procedure Decode_Sib (Sib : Byte; B_Mod : Bf_2)
- is
- S : Bf_2;
- I : Bf_3;
- B : Bf_3;
- begin
- S := Ext_Sib_Scale (Sib);
- B := Ext_Sib_Base (Sib);
- I := Ext_Sib_Index (Sib);
- Add_Char ('(');
- if B = 2#101# and then B_Mod /= 0 then
- Decode_Reg_Field (B, W_32);
- Add_Char (',');
- end if;
- if I /= 2#100# then
- Decode_Reg_Field (I, W_32);
- case S is
- when 2#00# =>
- null;
- when 2#01# =>
- Add_String (",2");
- when 2#10# =>
- Add_String (",4");
- when 2#11# =>
- Add_String (",8");
- end case;
- end if;
- Add_Char (')');
- end Decode_Sib;
-
- procedure Decode_Modrm_Mem (Off : in out Natural; Width : Width_Type)
- is
- B : Byte;
- B_Mod : Bf_2;
- B_Rm : Bf_3;
- Off_Orig : Natural;
- begin
- B := Mem (Off);
- B_Mod := Ext_Modrm_Mod (B);
- B_Rm := Ext_Modrm_Rm (B);
- Off_Orig := Off;
- case B_Mod is
- when 2#11# =>
- Decode_Reg_Field (B_Rm, Width);
- Off := Off + 1;
- when 2#10# =>
- if B_Rm = 2#100# then
- Off := Off + 2;
- Decode_Disp (Off, W_32);
- Decode_Sib (Mem (Off_Orig + 1), B_Mod);
- else
- Off := Off + 1;
- Decode_Disp (Off, W_32);
- Add_Char ('(');
- Decode_Reg_Field (B_Rm, W_32);
- Add_Char (')');
- end if;
- when 2#01# =>
- if B_Rm = 2#100# then
- Off := Off + 2;
- Decode_Disp (Off, W_8);
- Decode_Sib (Mem (Off_Orig + 1), B_Mod);
- else
- Off := Off + 1;
- Decode_Disp (Off, W_8);
- Add_Char ('(');
- Decode_Reg_Field (B_Rm, W_32);
- Add_Char (')');
- end if;
- when 2#00# =>
- if B_Rm = 2#100# then
- Off := Off + 2;
- Decode_Sib (Mem (Off_Orig + 1), B_Mod);
- elsif B_Rm = 2#101# then
- Off := Off + 1;
- Decode_Disp (Off, W_32);
- else
- Add_Char ('(');
- Decode_Reg_Field (B_Rm, W_32);
- Add_Char (')');
- Off := Off + 1;
- end if;
- end case;
- end Decode_Modrm_Mem;
-
- -- Return the length of the modrm bytes.
- -- At least 1 (mod/rm), at most 6 (mod/rm + SUB + disp32).
- function Decode_Modrm_Len (Off : Natural) return Natural
- is
- B : Byte;
- M_Mod : Bf_2;
- M_Rm : Bf_3;
- begin
- B := Mem (Off);
- M_Mod := Ext_Modrm_Mod (B);
- M_Rm := Ext_Modrm_Rm (B);
- case M_Mod is
- when 2#11# =>
- return 1;
- when 2#10# =>
- if M_Rm = 2#100# then
- return 1 + 1 + 4;
- else
- return 1 + 4;
- end if;
- when 2#01# =>
- if M_Rm = 2#100# then
- return 1 + 1 + 1;
- else
- return 1 + 1;
- end if;
- when 2#00# =>
- if M_Rm = 2#101# then
- -- disp32.
- return 1 + 4;
- elsif M_Rm = 2#100# then
- -- SIB
- return 1 + 1;
- else
- return 1;
- end if;
- end case;
- end Decode_Modrm_Len;
-
-
- Off : Natural;
- B : Byte;
- B1 : Byte;
- Desc : Insn_Desc_Type;
- Name : Index_Type;
- W : Width_Type;
- begin
- Mem := To_Pointer (Addr);
- Off := 0;
- Lo := Line'First;
-
- B := Mem (0);
- if B = 2#0000_1111# then
- B := Mem (1);
- Off := 2;
- Insn_Len := 2;
- Desc := Insn_Desc_0F (B);
- else
- Off := 1;
- Insn_Len := 1;
- Desc := Insn_Desc (B);
- end if;
-
- if Desc.Name >= G_1 then
- B1 := Mem (Off);
- case Desc.Name is
- when G_1
- | G_2 =>
- Name := Group_Name (Desc.Name, Ext_543 (B1));
- when G_3 =>
- Desc := Insn_Desc_G3 (Ext_543 (B1));
- Name := Desc.Name;
- when G_5 =>
- Desc := Insn_Desc_G5 (Ext_543 (B1));
- Name := Desc.Name;
- when others =>
- Desc := Desc_Invalid;
- end case;
- else
- Name := Desc.Name;
- end if;
-
- case Desc.Width is
- when W_Data =>
- W := W_Default;
- when W_8
- | W_16
- | W_32 =>
- W := Desc.Width;
- when W_None =>
- case Desc.Format is
- when Disp_8
- | Cond_Disp_8
- | Imm_8 =>
- W := W_8;
- when Disp_W
- | Cond_Disp_W =>
- W := W_Default;
- when Invalid
- | Opcode =>
- W := W_None;
- when others =>
- raise Program_Error;
- end case;
- end case;
-
- case Desc.Format is
- when Reg_Imp =>
- Add_Opcode (Desc.Name, W_Default);
- Decode_Reg_Field (Ext_210 (B), W_Default);
- when Opcode =>
- Add_Opcode (Desc.Name, W_None);
- when Modrm =>
- Add_Opcode (Desc.Name, W);
- Decode_Modrm_Mem (Insn_Len, W);
- when Modrm_Src =>
- Add_Opcode (Desc.Name, W);
- -- Disp source first.
- Decode_Modrm_Mem (Insn_Len, W);
- Add_Comma;
- B := Mem (Off);
- Decode_Modrm_Reg (Mem (Off), W);
- when Modrm_Dst =>
- Add_Opcode (Desc.Name, W);
- -- Disp source first.
- B := Mem (Off);
- Decode_Modrm_Reg (B, W);
- Add_Comma;
- Decode_Modrm_Mem (Insn_Len, W);
- when Modrm_Imm =>
- Add_Opcode (Name, W);
- Insn_Len := Off + Decode_Modrm_Len (Off);
- Decode_Imm (Insn_Len, W);
- Add_Comma;
- Decode_Modrm_Mem (Off, W);
- when Modrm_Imm_S =>
- Add_Opcode (Name, W);
- Insn_Len := Off + Decode_Modrm_Len (Off);
- Decode_Imm (Insn_Len, W_8);
- Add_Comma;
- Decode_Modrm_Mem (Off, W);
- when Modrm_Imm8 =>
- Add_Opcode (Name, W);
- Decode_Modrm_Mem (Off, W);
- Add_Comma;
- Decode_Imm (Off, W_8);
-
- when Reg_Imm =>
- Add_Opcode (Desc.Name, W);
- Decode_Imm (Insn_Len, W);
- Add_Comma;
- Decode_Reg_Field (Ext_210 (B), W);
- when Eax_Imm =>
- Add_Opcode (Desc.Name, W);
- Decode_Imm (Insn_Len, W);
- Add_Comma;
- Decode_Reg_Field (2#000#, W);
-
- when Disp_W
- | Disp_8 =>
- Add_Opcode (Desc.Name, W_None);
- Decode_Disp (Insn_Len, W,
- Pc + Unsigned_32 (Insn_Len + Width_Len (W)));
-
- when Cond_Disp_8
- | Cond_Disp_W =>
- Add_Cond_Opcode (Desc.Name, B);
- Decode_Disp (Insn_Len, W,
- Pc + Unsigned_32 (Insn_Len + Width_Len (W)));
-
- when Cond_Modrm =>
- Add_Cond_Opcode (Desc.Name, B);
- Decode_Modrm_Mem (Insn_Len, W);
-
- when Imm =>
- Add_Opcode (Desc.Name, W);
- Decode_Imm (Insn_Len, W);
-
- when Imm_S
- | Imm_8 =>
- Add_Opcode (Desc.Name, W);
- Decode_Imm (Insn_Len, W_8);
-
- when Modrm_Ax =>
- if (B and 2#1#) = 2#0# then
- W := W_8;
- else
- W := W_Default;
- end if;
- Add_Opcode (Desc.Name, W);
- Decode_Reg_Field (0, W);
- Add_Comma;
- Decode_Modrm_Mem (Off, W);
-
- when Ax_Off_Src =>
- Add_Opcode (Desc.Name, W);
- Decode_Disp (Insn_Len, W);
- Add_Comma;
- Decode_Reg_Field (0, W);
-
- when Ax_Off_Dst =>
- Add_Opcode (Desc.Name, W);
- Decode_Reg_Field (0, W);
- Add_Comma;
- Decode_Disp (Insn_Len, W);
-
- when Imp =>
- Add_Opcode (Desc.Name, W_Default);
-
- when Invalid
- | Prefix
- | Opcode2 =>
- Add_String ("invalid ");
- if Insn_Len = 2 then
- Add_Byte (Mem (0));
- end if;
- Add_Byte (B);
- Insn_Len := 1;
- end case;
-
- Line_Len := Lo - Line'First;
- end Disassemble_Insn;
-end Disa_X86;
-
-