home *** CD-ROM | disk | FTP | other *** search
- UNIT TPU6UNA;
-
- (*****************)
- (**) INTERFACE (**) USES TPU6EQU, TPU6AMS;
- (*****************)
-
- TYPE
- OprStr = String[32];
-
- CpuGate = (C086,C186,C286,C386);
-
- ObjArg =
- RECORD
- Obj : Word; { Offset of text to Unassemble }
- Lim : Word; { Max Bytes to Examine }
- TCpu : CpuGate; { Cpu code to handle }
- Locn : Word; { Code Offset }
- Code : OprStr; { Object Text in ASCII }
- Mnem : OprStr; { Mnemonic(s) in ASCII }
- Opr1 : OprStr; { ASCII Operand 1 }
- Opr2 : OprStr; { ASCII Operand 2 }
- Opr3 : OprStr; { ASCII Operand 3 }
- END;
-
- CONST SegDBit : Boolean = FALSE; { Assume 16-Bit Addressing }
-
- PROCEDURE UnAssemble(U : UnitPtr; VAR P : ObjArg);
-
- (**********************)
- (**) IMPLEMENTATION (**)
- (**********************)
-
- TYPE { Types Below Used For Quick Classification of Op-Codes }
-
- Gating =
- (G_RM1, G_RM2, G_RM3, G_RM4, G_RM5,
- G_RM6, G_RM7, G_RM8, G_RM9, { modR/M Has op bits }
- G_Hit, { defined operation }
- G_0Fx, { 0F-type operation }
- G_387, { escapes to 80387 }
- G_Pfx, { prefix operation }
- G_ooo); { invalid operation }
-
- Gate_2 = { 2nd-level gates for G_0Fx Operations }
- (Row_0,
- Row_2,
- Row_8,
- Row_9,
- Row_A,
- Row_B,
- Row_X); { invalid otherwise }
-
- TAdr = (Adr16,Adr32); {16-bit or 32-bit Addressing}
- WBitStatus = (W0,W1); {W1 = W-bit ON, else W0}
- REGString = String[3];
- TagRec =
- RECORD
- A : Char; {tells type of operand}
- V : Byte {gives width/value etc}
- END;
- TagGrp = ARRAY[1..3] OF TagRec;
-
- CpuVec =
- RECORD
- F, {Bit Flags for Processing Options}
- {1xxx xxxx = alternate Mnemonic at M+1 }
- {x1xx xxxx = 32-bit if OpSiz Prefix }
- {xx1x xxxx = 16-bit normally }
- {xxx1 xxxx = sign-extend immediates }
- {xxxx 1xxx = Op has modR/M field }
- {---- -ccc = Cpu Required for Op }
-
- M, {8086 Mnemonic Index}
- T {Operand Format Index}
- : Byte
- END;
-
- MpuVec = {.CP27}
- RECORD
- F, { Flag Bits (see below)
- 0000 0000 = INVALID operation
- 0010 xxxx = Entire modR/M byte defines op-code
- 0001 xxxx = modR/M REG field defines op-code
-
- xxxx 0000 = no explicit operand(s) coded
- xxxx 0001 = operand is "AX"
- xxxx 0010 = operand is "Bcd80"
- xxxx 0011 = operand is "Ea" (no size implied)
- xxxx 0100 = operand is "Ew" (16-bit word)
- xxxx 0101 = operand is "Int16"
- xxxx 0110 = operand is "Int32"
- xxxx 0111 = operand is "Int64"
- xxxx 1000 = operand is "Real32"
- xxxx 1001 = operand is "Real64"
- xxxx 1010 = operand is "Real80"
- xxxx 1011 = operand is "ST(i)"
- xxxx 1100 = operand is "ST(i),ST"
- xxxx 1101 = operand is "ST,ST(i)"
- xxxx 1110 = reserved
- xxxx 1111 = reserved
- }
- M { index to mnemonic table }
- : Byte
- END;
-
-
- TMrm =
- RECORD
- D, { Size in Bytes of Displacement Field}
- SIB, { 1 -> SIB field present, else no SIB}
- rS, { index to Segment Register String }
- rB, { index to Base Register String }
- rX { index to Index Register String }
- : Byte
- END;
-
- SibRec =
- RECORD
- D, { displacement width (bytes) }
- rS, { default segment register }
- rB { default base register }
- : Byte
- END;
-
- sxRec =
- RECORD
- rX, { to index reg name }
- sF { multiplier; if 0, ss must be too or illegal}
- : Byte
- END;
- {$I TPU6UNA.INC}
-
- VAR {.CP32}
- Is_386Xtnsn, Is_32BitMax, Is_16BitMin, Is_SignXtnd,
- Is_MODrmFld, HaveSizePfx, HaveAddrPfx, HaveMRM,
- HaveSIB, FetchFailure, DSiz32, ASiz32,
- HaveSegPfx, HaveInstPfx, HaveMemOprnd : Boolean;
-
- CpuAuth : CpuGate;
-
- CodeByte, PfxMax, OprBytes, DataByte,
- DLoc, mrmMOD, mrmREG, mrmRM,
- IPfx, sibSS, sibNDX, sibBAS,
- EmuFlag, SPfx : Byte;
-
- BytesFetched, BytesRemaining, PrefixBytes, CodeSeg,
- CodeOfs, VirtualIP : Word;
-
- REGOperand, REGSeg, REGBase,
- REGIndex, REGSegOvr : REGString;
-
- EAOperand, CodeText, Mnemonic : OprStr;
-
- CodeStack : ARRAY[1..16] OF Byte;
- Opnd : ARRAY[1..3] OF OprStr;
- ActGroup : CpuVec;
- OpTags : TagGrp;
- NdxSF : String[2];
-
- ByteGate : Gating;
- AddrMode : TAdr;
- WBitMode : WBitStatus;
-
- { --------------------------------------------- } {.CP19}
- { Fetches a Byte and stacks it for Disassembler }
- { --------------------------------------------- }
-
- FUNCTION FetchByte : Byte;
- BEGIN
- FetchFailure := BytesRemaining = 0;
- IF NOT FetchFailure THEN
- BEGIN
- Inc(BytesFetched);
- {$R+}
- CodeStack[BytesFetched] := Mem[CodeSeg:CodeOfs];
- {$R-}
- Dec(BytesRemaining);
- Inc(CodeOfs);
- END;
- FetchByte := CodeStack[BytesFetched]
- END;
-
- { ----------------------------------------------- } {.CP14}
- { Undoes the Fetch Byte Process - Pops From Stack }
- { ----------------------------------------------- }
-
- PROCEDURE UnFetchCodeByte;
- BEGIN
- IF BytesFetched > 0 THEN
- BEGIN
- Dec(BytesFetched);
- Inc(BytesRemaining);
- Dec(CodeOfs);
- END
- END;
-
- { ------------------------------------------------- } {.CP13}
- { Formats a Sequence of Stacked Bytes as printable }
- { Hex in "logical" order - not processor order, and }
- { appends a Padding String and a Blank }
- { ------------------------------------------------- }
-
- PROCEDURE FormatText(Locn, SLen:Byte; Pad : String);
- VAR W : OprStr; i : Byte;
- BEGIN
- W := '';
- FOR i := Locn TO Locn+SLen-1 DO W := HexB(CodeStack[i]) + W;
- CodeText := CodeText + W + Pad + ' ';
- END;
-
- { ------------------- } {.CP11}
- { Unpacks modR/M Byte }
- { ------------------- }
-
- PROCEDURE UnPackModRM(modRM : Byte);
- BEGIN
- HaveMRM := True;
- mrmMOD := (modRM SHR 6) AND $03;
- mrmREG := (modRM SHR 3) AND $07;
- mrmRM := modRM AND $07;
- END;
-
- { ---------------- } {.CP11}
- { Unpacks SIB Byte }
- { ---------------- }
-
- PROCEDURE UnPackSIB(sib : Byte);
- BEGIN
- HaveSIB := True;
- sibSS := (sib SHR 6) AND $03;
- sibNDX := (sib SHR 3) AND $07;
- sibBAS := sib AND $07;
- END;
-
- PROCEDURE MergeActGrp(VAR Z : CpuVec); {.CP10}
- VAR I,J : Byte;
- BEGIN
- ActGroup.M := Z.M;
- IF Z.T <> 0 THEN ActGroup.T := Z.T;
- I := ActGroup.F AND $7;
- J := Z.F AND $7;
- IF I < J THEN I := J;
- ActGroup.F := ((ActGroup.F OR Z.F) AND $F8) OR I;
- END;
-
- { ------------------------------------------------- } {.CP52}
- { Formats a Sequence of Stacked Bytes as printable }
- { Hex in "logical" order - not processor order for }
- { use in Operand Expressions. Lead zero suppressed }
- { May be SIGNED or UN-SIGNED }
- { ------------------------------------------------- }
-
- PROCEDURE FormatDispl(VAR Sx:OprStr; Locn, SLen:Byte; Signed:Boolean);
- TYPE
- MyWord = RECORD
- CASE Byte OF
- 0: (Ds : ShortInt);
- 1: (Db : Byte);
- 2: (Dw : Word);
- 3: (Di : Integer);
- 4: (Dd : LongInt);
- 5: (Dv : ARRAY[1..4] OF Byte);
- END;
-
- VAR W, X : MyWord; I : Byte; P : ^MyWord; Signit : Char;
- BEGIN
- Sx := '';
- IF SLen IN [1,2,4] THEN
- BEGIN
- P := @ CodeStack[Locn];
- W.Dd := 0; X := W;
- WITH P^ DO
- IF Signed THEN
- BEGIN { sign extend for next step }
- CASE SLen OF
- 1: W.Dd := Ds;
- 2: W.Dd := Di;
- 4: W.Dd := Dd
- END;
- X.Dd := Abs(W.Dd)
- END ELSE
- BEGIN { zero extend for next step }
- CASE SLen OF
- 1: W.Dd := Db;
- 2: W.Dd := Dw;
- 4: W.Dd := Dd
- END;
- X.Dd := W.Dd
- END;
- FOR i := 1 TO SLen DO Sx := HexB(X.Dv[i]) + Sx;
- IF X.Dd <> W.Dd
- THEN Signit := '-'
- ELSE Signit := '+';
- Sx := Sx + 'h';
- IF Signed THEN Sx := Signit + Sx;
- END;
- END; {FormatDispl}
-
- { ------------------------------------ } {.CP24}
- { ERROR - Stacked Code printed as DB's }
- { ------------------------------------ }
-
- PROCEDURE EmitConstants;
- VAR c : Char;
- BEGIN
- WHILE BytesFetched > 1 DO UnFetchCodeByte;
- Mnemonic := 'DB';
- CodeText := '';
- HaveInstPfx := False;
- c := Char(CodeStack[1]);
- CodeText := HexB(Byte(c));
- CASE c OF
- ' '..'&',
- '('..#$7F: Opnd[1] := '''' + c + '''';
- ELSE Opnd[1] := '0' + CodeText + 'h';
- END;
- Opnd[2] := '';
- Opnd[3] := '';
- { Ready to Build and Print Line }
- END;
-
- { --------------------- } {.CP08}
- { Returns Register Name }
- { --------------------- }
-
- FUNCTION ExtractReg(Am : TAdr; Wbit : WBitStatus; Arg : Byte) : RegString;
- BEGIN
- ExtractReg := RegList[RegDecode[Am,Wbit,Arg]]
- END;
-
- { ----------------------------------- } {.CP12}
- { Fetches Displacement/Immediate Data }
- { ----------------------------------- }
-
- FUNCTION FetchDispl(Width:Byte) : Byte; { Index to LSB of Displ }
- VAR i, j : Byte;
- BEGIN
- FOR i := 1 TO Width DO j := FetchByte;
- IF FetchFailure
- THEN FetchDispl := 0
- ELSE FetchDispl := BytesFetched + 1 - Width;
- END;
-
- { ------------------------------- } {.CP05}
- { Decodes and Stacks Prefix Bytes }
- { ------------------------------- }
-
- PROCEDURE HandlePrefix;
-
- PROCEDURE StowPrefix; {.CP45}
- CONST PfxFlg : ARRAY[1..4] OF CHAR = '>||:';
- VAR PfxCls : 1..4; i : Byte;
- BEGIN
- CASE CodeByte OF
- $F0, $F2..$F3: BEGIN {LOCK/REPE/REPNE}
- PfxCls := 1;
- IPfx := CodeByte;
- HaveInstPfx := True;
- END;
- $67: BEGIN {Address Size Prefix}
- PfxCls := 2;
- ASiz32 := NOT SegDBit;
- HaveAddrPfx := True;
- END;
- $66: BEGIN {Operand Size Prefix}
- PfxCls := 3;
- DSiz32 := NOT SegDBit;
- HaveSizePfx := True;
- END;
- $26,$2E,
- $36,$3E: BEGIN {Segment Prefix ES,CS,SS,DS}
- PfxCls := 4;
- SPfx := BytesFetched;
- HaveSegPfx := True;
- i := CodeByte SHR 3 AND $03;
- REGSegOvr := RegList[i + 24];
- END;
- $64,$65: BEGIN {Segment Prefix FS,GS}
- PfxCls := 4;
- SPfx := BytesFetched;
- HaveSegPfx := True;
- i := CodeByte AND $07;
- REGSegOvr := RegList[i + 24];
- END;
- END;
- IF PfxCls > PfxMax THEN
- BEGIN
- Inc(PrefixBytes);
- PfxMax := PfxCls;
- FormatText(BytesFetched,1,PfxFlg[PfxCls]);
- END ELSE
- BEGIN
- UnFetchCodeByte; { will fetch again later }
- EmitConstants; { emit code stack as DB's }
- PrefixBytes := 0; PfxMax := 0;
- HaveAddrPfx := False; HaveSizePfx := False;
- END;
- END; {StowPrefix}
-
- BEGIN {HandlePrefix} {.CP05}
- IF NOT FetchFailure THEN
- IF (ActLvl1[CodeByte].F AND $7) > Ord(CpuAuth) THEN
- BEGIN EmitConstants; ByteGate := G_ooo END ELSE
- BEGIN
- StowPrefix;
- CodeByte := FetchByte;
- IF NOT FetchFailure
- THEN ByteGate := GateLvl1[CodeByte]
- ELSE ByteGate := G_ooo;
- END;
- END; {HandlePrefix}
-
- { -------------------------------------- } {.CP44}
- { Interprets modR/M and optional SIB to }
- { get operand strings. Fetches required }
- { displacement fields if any. }
- { -------------------------------------- }
-
- PROCEDURE DecodeModRM(W :WBitStatus);
- VAR wmrm : TMrm; wsib : SibRec; wsx : sxRec; Sx : OprStr;
- BEGIN
- IF mrmMOD = 3 THEN EAOperand := ExtractReg(AddrMode,W,mrmRM)
- ELSE
- BEGIN
- wmrm := MrmTab[AddrMode,mrmMOD,mrmRM];
- IF wmrm.SIB = 1 THEN
- BEGIN
- DataByte := FetchByte;
- FormatText(BytesFetched,1,'');
- UnPackSIB(DataByte);
- wsib := SibTab[mrmMOD,sibBAS];
- wsx := sxTAB[sibSS,sibNDX];
- wmrm.D := wsib.D;
- wmrm.rS := wsib.rS;
- wmrm.rB := wsib.rB;
- wmrm.rX := wsx.rX;
- IF wsx.SF = 0 THEN
- BEGIN
- NdxSF := '';
- wmrm.rX := 30 { null register string }
- END
- ELSE NdxSF := '*'+Chr(Ord('0')+wsx.SF);
- END;
-
- DLoc := FetchDispl(wmrm.D);
- FormatText(DLoc,wmrm.D,'');
- FormatDispl(Sx,DLoc,wmrm.D,True);
- REGSeg := RegList[wmrm.rS];
- REGBase := RegList[wmrm.rB];
- REGIndex := RegList[wmrm.rX];
- EAOperand := REGBase;
- IF Length(REGIndex) > 0
- THEN EAOperand := EAOperand + '+' + REGIndex + NdxSF;
- IF wmrm.D > 0 THEN EAOperand := EAOperand + Sx;
- END;
- REGOperand := ExtractReg(AddrMode,W,mrmREG);
- END;
-
- { ---------------------------------- } {.CP08}
- { Main Driver for 80386 Operand Edit }
- { ---------------------------------- }
-
- PROCEDURE Edit386Ops;
- VAR
- OpEdit : TagRec; Sx : OprStr;
- i : Byte;
-
- PROCEDURE EditSplRegs(j : Byte); { CRx,DRx,TRx } {.CP04}
- BEGIN
- Opnd[j] := OpEdit.A + 'R' + Chr(Ord('0')+mrmREG);
- END;
-
- PROCEDURE EditDblRegs(j : Byte); { EAX..EDI } {.CP04}
- BEGIN
- Opnd[j] := RegList[16+mrmREG];
- END;
-
- PROCEDURE EditSegRegs(j : Byte); { ES:..GS: } {.CP04}
- BEGIN
- Opnd[j] := RegList[24+mrmREG];
- END;
-
- PROCEDURE EditLiteral(j : Byte); { literal data } {.CP04}
- BEGIN
- Opnd[j] := RegList[OpEdit.V];
- END;
-
- PROCEDURE EditGprRegs(j : Byte); { Gb,Gw,Gd,Gv } {.CP04}
- BEGIN
- Opnd[j] := REGOperand;
- END;
-
- PROCEDURE EditJmpDspl(j : Byte); { Jb, Jv } {.CP17}
- TYPE
- MyWord = RECORD
- CASE Byte OF
- 0: (Ds : ShortInt);
- 1: (Db : Byte);
- 2: (Dw : Word);
- 3: (Di : Integer);
- 4: (Dd : LongInt);
- 5: (Dv : ARRAY[1..4] OF Byte);
- END;
-
- VAR P : ^MyWord; i,k : Byte; l : LongInt;
- BEGIN
- IF RegList[OpEdit.V][1] = 'b' THEN
- BEGIN
- i := FetchDispl(1);
- FormatText(i,1,'');
- P := @ CodeStack[i];
- l := CodeOfs + P^.Ds;
- P := @l;
- Opnd[j] := 'SHORT ' + HexB(Hi(P^.Dw))+HexB(Lo(P^.Dw))+'h';
- END ELSE
- BEGIN
- IF ASiz32 THEN k := 4 ELSE k := 2;
- i := FetchDispl(k); { Displacement }
- FormatText(i,k,'');
- P := @ CodeStack[i];
- IF ASiz32
- THEN l := CodeOfs + P^.Dd
- ELSE l := CodeOfs + P^.Di;
- P := @l;
- Opnd[j] := 'h';
- FOR i := 1 TO k DO
- Opnd[j] := HexB(P^.Dv[i]) + Opnd[j]
- END;
- END;
-
- PROCEDURE EditPointer(j : Byte); { Ap } {.CP13}
- VAR i,k : Byte;
- BEGIN
- IF ASiz32 THEN k := 4 ELSE k := 2;
- i := FetchDispl(k); { Displacement }
- FormatText(i,k,'r');
- FormatDispl(Sx,i,k,False);
- k := 2;
- i := FetchDispl(k); { Selector }
- FormatText(i,k,'s');
- FormatDispl(Opnd[j],i,k,False);
- Opnd[j] := Opnd[j] + ':' + Sx;
- END;
-
- PROCEDURE EditImmData(j : Byte); { Ib, Iv, Iw } {.CP17}
- VAR i,k : Byte;
- BEGIN
- CASE RegList[OpEdit.V][1] OF
- 'b': k := 1;
- 'w': k := 2;
- 'v': IF DSiz32 THEN k := 4 ELSE k := 2;
- ELSE k := 0
- END; {CASE}
- IF k > 0 THEN
- BEGIN
- i := FetchDispl(k);
- FormatText(i,k,'');
- FormatDispl(Sx,i,k,Is_SignXtnd);
- Opnd[j] := Sx;
- END;
- END;
-
- PROCEDURE EditMemAddr(j : Byte); {.CP04}
- BEGIN
- Opnd[j] := '';
- IF HaveSegPfx THEN Opnd[j] := REGSegOvr + ': ';
- Opnd[j] := '['+ Opnd[j] + EAOperand + ']';
- HaveMemOprnd := True;
- END;
-
- PROCEDURE EditOfsDspl(j : Byte); { Ob, Ov } {.CP16}
- VAR i,k : Byte;
- BEGIN
- CASE RegList[OpEdit.V][1] OF
- 'b': k := 2;
- 'v': IF ASiz32 THEN k := 4 ELSE k := 2;
- ELSE k := 0
- END; {CASE}
- IF k > 0 THEN
- BEGIN
- i := FetchDispl(k); { Offset }
- FormatText(i,k,'');
- FormatDispl(Sx,i,k,False);
- IF HaveSegPfx AND (mrmMOD <> 3)
- THEN Sx := REGSegOvr + ': ' + Sx;
- Opnd[j] := '[' + Sx + ']';
- HaveMemOprnd := True;
- END;
- END;
-
- PROCEDURE EditEffAddr(j : Byte); { Eb, Ew, Ev, Ep } {.CP22}
- BEGIN
- Sx := '';
- IF mrmMOD <> 3 THEN
- IF j = 1 THEN
- CASE RegList[OpEdit.V][1] OF
- 'b': Sx := 'BYTE';
- 'w': Sx := 'WORD';
- 'v': IF DSiz32
- THEN Sx := 'DWORD'
- ELSE Sx := 'WORD';
- 'p': IF ASiz32
- THEN Sx := 'FWORD'
- ELSE Sx := 'DWORD';
- 'q': Sx := 'QWORD';
- 't': Sx := 'TBYTE';
- 'd': Sx := 'DWORD';
- END; {CASE}
- IF Sx <> '' THEN Sx := Sx + ' PTR ';
- IF HaveSegPfx AND (mrmMOD <> 3)
- THEN Sx := REGSegOvr + ': ' + Sx;
- Opnd[j] := Sx + EAOperand;
- IF mrmMOD <> 3
- THEN BEGIN
- Opnd[j] := '[' + Opnd[j] + ']';
- HaveMemOprnd := True;
- END;
- END;
-
- PROCEDURE EditVarRegs(j : Byte); { eAX..eDI } {.CP04}
- BEGIN
- Opnd[j] := RegList[OpEdit.V+(Ord(DSiz32) SHL 3)];
- END;
-
- BEGIN {Edit386Ops} {.CP22}
-
- FOR i := 1 TO 3 DO BEGIN
- OpEdit := OpTags[i];
- Opnd[i] := '';
- CASE OpEdit.A OF
- 'C',
- 'D',
- 'T': EditSplRegs(i);
- 'A': EditPointer(i);
- 'R': EditDblRegs(i);
- 'S': EditSegRegs(i);
- 'G': EditGprRegs(i);
- 'J': EditJmpDspl(i);
- 'I': EditImmData(i);
- 'M': EditMemAddr(i);
- 'O': EditOfsDspl(i);
- 'E': EditEffAddr(i);
- 'e': EditVarRegs(i);
- 'r': EditLiteral(i);
- END; {CASE}
- END;
- END; {Edit386Ops}
-
- PROCEDURE RemovePrefix;
- BEGIN
- WHILE BytesFetched > SPfx DO UnFetchCodeByte;
- IF SPfx <> 1 THEN
- BEGIN
- UnFetchCodeByte;
- EmitConstants;
- END ELSE
- BEGIN
- CodeByte := CodeStack[SPfx];
- CodeText := '';
- FormatText(SPfx,1,'');
- ActGroup := ActLvl1[CodeByte];
- Opnd[1] := '';
- Opnd[2] := '';
- Opnd[3] := '';
- Mnemonic := Mnem386[ActGroup.M];
- END;
- END;
-
- { ---------------------------------- } {.CP05}
- { Main Driver for 80386 Instructions }
- { ---------------------------------- }
-
- PROCEDURE Handle386Op;
- VAR i : Byte; OGate : Gating;
-
- PROCEDURE UpdateTags(n : Byte);
- VAR i : Byte;
- BEGIN
- FOR i := 1 TO 3 DO
- IF OpType386[n,i].A <> ' ' THEN OpTags[i] := OpType386[n,i];
- END;
-
- PROCEDURE HandleOpMRM; {.CP17}
- BEGIN
- DataByte := FetchByte;
- IF NOT FetchFailure THEN
- BEGIN
- FormatText(BytesFetched,1,'');
- UnPackModRM(DataByte);
- OGate := ByteGate;
- ByteGate := GateLvl3[ByteGate,mrmREG];
- IF ByteGate = G_Hit THEN
- BEGIN
- MergeActGrp(ActLvl3[OGate,mrmREG]);
- UpdateTags(ActGroup.T);
- END;
- END;
- END; {HandleOpMRM}
-
- PROCEDURE HandleOp0Fx; {.CP19}
- VAR RowNdx : Gate_2; ColNdx : $0..$F;
- BEGIN
- CodeByte := FetchByte;
- IF NOT FetchFailure THEN
- BEGIN
- FormatText(BytesFetched,1,'');
- RowNdx := GateLvX2[(CodeByte SHR 4) AND $0F];
- ColNdx := CodeByte AND $0F;
- ByteGate := GateLvl2[RowNdx,ColNdx];
- CASE ByteGate OF
- G_Hit: BEGIN
- MergeActGrp(ActLvl2[RowNdx,ColNdx]);
- UpdateTags(ActGroup.T);
- END;
- G_RM6..G_RM8: HandleOpMRM;
- END; {CASE}
- END;
- END; {HandleOp0FX}
-
- BEGIN {Handle386Op} {.CP34}
- FormatText(BytesFetched,1,'');
- WITH ActLvl1[CodeByte] DO BEGIN
- ActGroup.F := F;
- ActGroup.M := M;
- ActGroup.T := T;
- OpTags := OpType386[ActGroup.T];
- END;
- Case ByteGate OF
- G_RM1..G_RM9: HandleOpMRM;
- G_0Fx: HandleOp0Fx;
- G_Hit:;
- END;
- IF (ActGroup.F AND $7) > Ord(CpuAuth) THEN ByteGate := G_ooo;
- IF NOT FetchFailure AND (ByteGate <> G_ooo) THEN
- BEGIN
- Is_386Xtnsn := (ActGroup.F AND _386Xtnsn) = _386Xtnsn;
- Is_32BitMax := (ActGroup.F AND _32BitMax) = _32BitMax;
- Is_16BitMin := (ActGroup.F AND _16BitMin) = _16BitMin;
- Is_SignXtnd := (ActGroup.F AND _SignXtnd) = _SignXtnd;
- Is_MODrmFld := (ActGroup.F AND _MODrmFld) = _MODrmFld;
- IF Is_MODrmFld AND NOT HaveMRM THEN
- BEGIN
- CodeByte := FetchByte;
- IF NOT FetchFailure THEN UnPackModRM(CodeByte);
- FormatText(BytesFetched,1,'');
- END;
- IF Is_32BitMax OR Is_16BitMin THEN WBitMode := W1;
- END;
- IF FetchFailure OR (ByteGate = G_ooo) OR (ActGroup.M = 0)
- THEN EmitConstants ELSE
- BEGIN
- IF DSiz32 AND Is_386Xtnsn
- THEN Mnemonic := Mnem386[ActGroup.M+1]
- ELSE Mnemonic := Mnem386[ActGroup.M];
- IF HaveMRM THEN DecodeModRM(WBitMode);
- Edit386Ops;
- IF HaveSegPfx AND (NOT HaveMemOprnd)
- THEN RemovePrefix ELSE
- BEGIN
- EmuFlag := 0;
- IF (BytesFetched = 2) AND (CodeStack[1] = $CD) THEN
- CASE CodeStack[2] OF
- $34..$3B,
- $3E: BEGIN
- EmuFlag := CodeStack[2];
- Opnd[3] := '; F-P Emulator Linkage';
- END;
- $3C: BEGIN
- EmuFlag := CodeStack[2];
- Opnd[3] := '; Emulated SEG Prefix';
- END;
- $3D: Opnd[3] := '; Emulated FWAIT ';
- END;
- END;
- { emit instruction }
- END;
- END; {Handle386Op}
-
- { ----------------------------------------- } {.CP50}
- { Main driver for Co-Processor Instructions }
- { ----------------------------------------- }
-
- PROCEDURE Handle387Op(Emulation : Boolean);
- CONST T : ARRAY[2..10] OF Byte = (41,37,39,39,35,40,35,40,41);
- VAR esc,flaga,flagop :byte; MpuAux : MpuVec;
- stkr : char;
-
- BEGIN
- esc := CodeByte AND $07;
- IF NOT Emulation THEN FormatText(BytesFetched,1,'');
- CodeByte := FetchByte;
- IF NOT FetchFailure THEN UnPackModRM(CodeByte);
- FormatText(BytesFetched,1,'');
- IF mrmMOD = 3 THEN
- BEGIN
- MpuAux := MpuM11[esc,mrmREG]; {flags,link}
- MpuAux.M := MpuOv[MpuAux.M,mrmRM] { mnemonic }
- END
- ELSE
- MpuAux := MpuEA[esc,mrmREG]; {flags,mnemonic}
-
- flaga := MpuAux.F SHR 4;
- IF flaga = 0 THEN EmitConstants ELSE
- BEGIN
- flagop := MpuAux.F AND $0F;
- stkr := Chr(Ord('0')+mrmRM);
- CASE flagop OF
- 0: Opnd[1] := '';
- 1: Opnd[1] := 'AX';
- 2..10: BEGIN
- DecodeModRM(W0);
- OpTags := OpType386[96];
- OpTags[1].V := T[flagop];
- Edit386Ops;
- END;
- 11: Opnd[1] := 'ST('+stkr+')';
- 12: Opnd[1] := 'ST('+stkr+'),ST';
- 13: Opnd[1] := 'ST,ST('+stkr+')';
- END;
- Mnemonic := Mnem387[MpuAux.M];
- Opnd[2] := '';
- Opnd[3] := '';
- { Emit Instruction Here }
- END;
- END; {Handle387Op}
-
- { ----------------------------------------- } {.CP17}
- { Main Driver for ALL Instruction Sequences }
- { ----------------------------------------- }
-
- PROCEDURE HandleInstruction;
- BEGIN
- ByteGate := GateLvl1[CodeByte];
- WHILE ByteGate = G_Pfx DO HandlePrefix;
- IF ASiz32 THEN AddrMode := Adr32 ELSE AddrMode := Adr16;
- IF NOT FetchFailure THEN
- CASE ByteGate OF
- G_RM1..G_0Fx: Handle386Op; {Get Op and modR/M}
- G_387: Handle387Op(False); { Ndp Ops }
- ELSE EmitConstants {Invalid Op Codes }
- END;
- END;
-
- { -------------------------------- } {.CP34}
- { Initialize for Instruction Fetch }
- { -------------------------------- }
-
- PROCEDURE StartOpFetch; { Initializes for next Instruction }
- BEGIN
- Is_386Xtnsn := False; Is_32BitMax := False;
- Is_16BitMin := False; Is_SignXtnd := False;
- Is_MODrmFld := False;
- HaveSizePfx := False; HaveAddrPfx := False;
- HaveMRM := False; HaveSIB := False;
- FetchFailure := False; HaveMemOprnd := False;
- HaveInstPfx := False; HaveSegPfx := False;
- ASiz32 := SegDBit; DSiz32 := SegDBit;
-
- CodeByte := 0; OprBytes := 0;
- BytesFetched := 0; mrmMOD := 0;
- mrmREG := 0; mrmRM := 0;
- sibSS := 0; sibNDX := 0;
- sibBAS := 0; PfxMax := 0;
- PrefixBytes := 0; DLoc := 0;
- SPfx := 0;
-
- CodeText := ''; NdxSF := '';
- EAOperand := ''; REGSeg := '';
- REGBase := ''; REGIndex := '';
- REGOperand := ''; REGSegOvr := '';
-
- WBitMode := W0; AddrMode := Adr16;
- ActGroup.F := 0; ActGroup.M := 0;
- ActGroup.T := 0; VirtualIP := CodeOfs;
-
- CodeByte := FetchByte;
- END;
-
- { ------------------------------------- } {.CP11}
- { Prototype For Disassembly of One Line }
- { ------------------------------------- }
-
- PROCEDURE DisassembleLine;
- BEGIN
- StartOpFetch;
- CASE EmuFlag OF {Handle Turbo F-P Emulator Expansions}
- $34..$3B : BEGIN
- UnFetchCodeByte;
- CodeByte := EmuFlag + $A4;
- Handle387Op(True);
- Mnemonic := 'EMU_'+Mnemonic;
- EmuFlag := 0;
- Opnd[3] := '; Emulated Operation';
- END;
- $3C: BEGIN
- HaveSegPfx := True;
- REGSegOvr := RegList[24+(CodeByte SHR 6 XOR 3)];
- Handle387Op(False);
- Mnemonic := 'EMU_'+Mnemonic;
- EmuFlag := 0;
- Opnd[3] := '; Emulated Operation';
- END;
- $3E: BEGIN { DB xxH for parameters }
- EmitConstants;
- Opnd[3] := '; Fast Path Emulations ';
- EmuFlag := 0;
- END;
- ELSE BEGIN
- HandleInstruction;
- IF HaveInstPfx
- THEN
- Mnemonic := Mnem386[ActLvl1[IPfx].M] + ' ' + Mnemonic;
- END
- END; {CASE}
- END;
-
- PROCEDURE UnAssemble(U : UnitPtr; VAR P : ObjArg);
- BEGIN
- WITH P DO BEGIN
- IF NOT (TCpu IN [C086..C386]) THEN TCpu := C086;
- CpuAuth := TCpu;
- CodeSeg := Seg(BufPtr(U)^.BufByt[Obj]);
- CodeOfs := Ofs(BufPtr(U)^.BufByt[Obj]);
- BytesRemaining := Lim;
- VirtualIP := Obj;
- Locn := 0;
- Code := '';
- Mnem := '';
- Opr1 := '';
- Opr2 := '';
- Opr3 := '';
- END;
- DisAssembleLine;
- WITH P DO BEGIN
- Obj := Obj+BytesFetched;
- Lim := BytesRemaining;
- Code := CodeText;
- Mnem := Mnemonic;
- Opr1 := Opnd[1];
- Opr2 := Opnd[2];
- Opr3 := Opnd[3];
- Locn := VirtualIP;
- END;
- END;
- BEGIN
- EmuFlag := $0; {No Borland/Microsoft F-P Emulator in Progress}
- END.
-