diff options
Diffstat (limited to 'ortho/mcode/disa_sparc.adb')
-rw-r--r-- | ortho/mcode/disa_sparc.adb | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/ortho/mcode/disa_sparc.adb b/ortho/mcode/disa_sparc.adb new file mode 100644 index 0000000..8c9176f --- /dev/null +++ b/ortho/mcode/disa_sparc.adb @@ -0,0 +1,274 @@ +with System; use System; +with Interfaces; use Interfaces; +with Ada.Unchecked_Conversion; +with Hex_Images; use Hex_Images; + +package body Disa_Sparc is + subtype Reg_Type is Unsigned_32 range 0 .. 31; + + type Hex_Map_Type is array (Unsigned_32 range 0 .. 15) of Character; + Hex_Digit : constant Hex_Map_Type := "0123456789abcdef"; + + type Cstring_Acc is access constant String; + type Cond_Map_Type is array (Unsigned_32 range 0 .. 15) of Cstring_Acc; + subtype S is String; + Bicc_Map : constant Cond_Map_Type := + (0 => new S'("n"), + 1 => new S'("e"), + 2 => new S'("le"), + 3 => new S'("l"), + 4 => new S'("leu"), + 5 => new S'("cs"), + 6 => new S'("neg"), + 7 => new S'("vs"), + 8 => new S'("a"), + 9 => new S'("ne"), + 10 => new S'("g"), + 11 => new S'("ge"), + 12 => new S'("gu"), + 13 => new S'("cc"), + 14 => new S'("pos"), + 15 => new S'("vc") + ); + + + type Format_Type is + ( + Format_Bad, + Format_Regimm, -- format 3, rd, rs1, rs2 or imm13 + Format_Rd, -- format 3, rd only. + Format_Copro, -- format 3, fpu or coprocessor + Format_Asi -- format 3, rd, rs1, asi and rs2. + ); + + type Insn_Desc_Type is record + Name : Cstring_Acc; + Format : Format_Type; + end record; + + type Insn_Desc_Array is array (Unsigned_32 range 0 .. 63) of Insn_Desc_Type; + Insn_Desc_10 : constant Insn_Desc_Array := + ( + 2#000_000# => (new S'("add"), Format_Regimm), + 2#000_001# => (new S'("and"), Format_Regimm), + 2#000_010# => (new S'("or"), Format_Regimm), + 2#000_011# => (new S'("xor"), Format_Regimm), + 2#000_100# => (new S'("sub"), Format_Regimm), + 2#000_101# => (new S'("andn"), Format_Regimm), + 2#000_110# => (new S'("orn"), Format_Regimm), + 2#000_111# => (new S'("xnor"), Format_Regimm), + 2#001_000# => (new S'("addx"), Format_Regimm), + + 2#001_100# => (new S'("subx"), Format_Regimm), + + 2#010_000# => (new S'("addcc"), Format_Regimm), + 2#010_001# => (new S'("andcc"), Format_Regimm), + 2#010_010# => (new S'("orcc"), Format_Regimm), + 2#010_011# => (new S'("xorcc"), Format_Regimm), + 2#010_100# => (new S'("subcc"), Format_Regimm), + 2#010_101# => (new S'("andncc"), Format_Regimm), + 2#010_110# => (new S'("orncc"), Format_Regimm), + 2#010_111# => (new S'("xnorcc"), Format_Regimm), + 2#011_000# => (new S'("addxcc"), Format_Regimm), + + 2#011_100# => (new S'("subxcc"), Format_Regimm), + + 2#111_000# => (new S'("jmpl"), Format_Regimm), + + 2#111_100# => (new S'("save"), Format_Regimm), + 2#111_101# => (new S'("restore"), Format_Regimm), + + others => (null, Format_Bad) + ); + + Insn_Desc_11 : constant Insn_Desc_Array := + ( + 2#000_000# => (new S'("ld"), Format_Regimm), + 2#000_001# => (new S'("ldub"), Format_Regimm), + 2#000_010# => (new S'("lduh"), Format_Regimm), + 2#000_011# => (new S'("ldd"), Format_Regimm), + 2#000_100# => (new S'("st"), Format_Regimm), + 2#000_101# => (new S'("stb"), Format_Regimm), + + 2#010_000# => (new S'("lda"), Format_Asi), + 2#010_011# => (new S'("ldda"), Format_Asi), + + 2#110_000# => (new S'("ldc"), Format_Regimm), + 2#110_001# => (new S'("ldcsr"), Format_Regimm), + + others => (null, Format_Bad) + ); + + -- Disassemble instruction at ADDR, and put the result in LINE/LINE_LEN. + procedure Disassemble_Insn (Addr : Address; + Line : in out String; + Line_Len : out Natural; + Insn_Len : out Natural; + Proc_Cb : Symbol_Proc_Type) + is + type Unsigned_32_Acc is access Unsigned_32; + function To_Unsigned_32_Acc is new Ada.Unchecked_Conversion + (Source => Address, Target => Unsigned_32_Acc); + + W : Unsigned_32; + Lo : Natural; + + -- Add CHAR to the line. + procedure Add_Char (C : Character); + pragma Inline (Add_Char); + + procedure Add_Char (C : Character) is + begin + Line (Lo) := C; + Lo := Lo + 1; + end 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 Disp_Const (Mask : Unsigned_32) + is + L : Natural; + V : Unsigned_32; + begin + L := Lo; + Proc_Cb.all (Addr, Line (Lo .. Line'Last), Lo); + V := W and Mask; + + -- Extend sign. + if (W and ((Mask + 1) / 2)) /= 0 then + V := V or not Mask; + end if; + if L /= Lo then + if V = 0 then + return; + end if; + Add_String (" + "); + end if; + Add_String ("0x"); + Add_String (Hex_Image (V)); + end Disp_Const; + + procedure Add_Cond (Str : String) + is + begin + Add_String (Str); + Add_String (Bicc_Map (Shift_Right (W, 25) and 2#1111#).all); + if (W and 16#2000_0000#) /= 0 then + Add_String (",a"); + end if; + Add_Char (' '); + Disp_Const (16#3f_Ffff#); + end Add_Cond; + + + procedure Add_Ireg (R : Reg_Type) + is + begin + Add_Char ('%'); + if R <= 7 then + Add_Char ('g'); + elsif R <= 15 then + if R = 14 then + Add_String ("sp"); + return; + else + Add_Char ('o'); + end if; + elsif R <= 23 then + Add_Char ('l'); + else + if R = 30 then + Add_String ("fp"); + return; + else + Add_Char ('i'); + end if; + end if; + Add_Char (Hex_Digit (R and 7)); + end Add_Ireg; + + procedure Disp_Unknown is + begin + Add_String ("unknown "); + Add_String (Hex_Image (W)); + end Disp_Unknown; + + procedure Disp_Format3 (Map : Insn_Desc_Array) + is + Op2 : Unsigned_32 range 0 .. 63; + begin + Op2 := Shift_Right (W, 19) and 2#111_111#; + + case Map (Op2).Format is + when Format_Regimm => + Add_String (Map (Op2).Name.all); + Add_Char (' '); + Add_Ireg (Shift_Right (W, 25) and 31); + Add_Char (','); + Add_Ireg (Shift_Right (W, 14) and 31); + Add_Char (','); + if (W and 16#2000#) /= 0 then + Disp_Const (16#1fff#); + else + Add_Ireg (W and 31); + end if; + when others => + Add_String ("unknown3, op2="); + Add_String (Hex_Image (Op2)); + end case; + end Disp_Format3; + + + begin + W := To_Unsigned_32_Acc (Addr).all; + Insn_Len := 4; + Lo := Line'First; + + case Shift_Right (W, 30) is + when 2#00# => + -- BIcc, SETHI + case Shift_Right (W, 22) and 2#111# is + when 2#000# => + Add_String ("unimp "); + Disp_Const (16#3f_Ffff#); + when 2#010# => + Add_Cond ("b"); + when 2#100# => + Add_String ("sethi "); + Add_Ireg (Shift_Right (W, 25)); + Add_String (", "); + Disp_Const (16#3f_Ffff#); + when others => + Disp_Unknown; + end case; + when 2#01# => + -- Call + Add_String ("call "); + Disp_Const (16#3fff_Ffff#); + when 2#10# => + Disp_Format3 (Insn_Desc_10); + when 2#11# => + Disp_Format3 (Insn_Desc_11); + when others => + -- Misc. + Disp_Unknown; + end case; + + Line_Len := Lo - Line'First; + end Disassemble_Insn; + +end Disa_Sparc; |