bobc@tikal.UUCP (Bob Campbell) (09/11/85)
Here is the Disassembler that I announced in net.micro.mac
# The rest of this file is a shell script which will extract:
# README DecIO.DEF Disasm.DEF DecIO.MOD DecLink.MOD Disasm.MOD
echo x - README
cat >README <<'!Funky!Stuff!'
These files (DecIO.DEF DecIO.MOD DecLink.MOD Disasm.DEF Disasm.MOD)
are the modula-2 source for a 68000 disassembler for Modula-2 Link
files (.LNK ext). The modules function as follows:
DecLink.MOD:
This is the main module, it breaks the link file up in to it parts
and calls the decoding routines to print out the various parts.
DecIO.MOD DecIO.DEF:
This module defines all of the I/O Routines, it opens the input file,
and the output file (the routine StartIO). It also provides general
input and output routines. Output goes to the input file name
conveterted to .DEC.
The Output Routines are:
WriteHex, WriteHexAdr, WriteCard, WriteInt, WriteDigit,
printChecksum, ErrorMessage, Write (*a character*), WriteLn,
WriteString, TabTo, WriteBlanks,
The Input Routines are:
Read (* a word *), and ReadBlock
Startup is StartIO, cleanup is EndIO.
Disasm.MOD Disasm.DEF:
This module is the disassembler proper it imports routines from
DecIO to format and print. It receives the data to disassemble
as a address to a block of data, a load point, and the number of
bytes to disassemble.
This program is compiled by first compiling all of the .DEF files,
and then all of the .MOD files. Then the file DecLink.LNK is linked
and the program can be run.
Because of problems with the SFPackage and the M2Files Interface you
can only open files which are on the same disk as the Exec program is.
This is because SFPackage returns a File Name and the Vol #, but the
M2Files open only takes a strings of the form VOLUME:FILE. I have not
yet figured out a solution to this problem.
!Funky!Stuff!
echo x - DecIO.DEF
cat >DecIO.DEF <<'!Funky!Stuff!'
DEFINITION MODULE DecIO;
FROM SYSTEM IMPORT WORD,ADDRESS;
FROM M2Files IMPORT File;
FROM QuickDraw IMPORT Str255;
EXPORT QUALIFIED WriteHex,WriteHexAdr,WriteCard,WriteInt,WriteDigit,
checksum,printChecksum,ErrorMessage,StartIO,EndIO,
Read,ReadBlock,Write,WriteLn,WriteString,
WriteBlanks,LinkStream,TabTo;
VAR
checksum: CARDINAL;
printChecksum: BOOLEAN;
LinkStream,decStream: File;
PROCEDURE ErrorMessage(VAR str: ARRAY OF CHAR);
PROCEDURE TabTo(col:CARDINAL);
PROCEDURE StartIO(VAR found:BOOLEAN);
PROCEDURE EndIO;
PROCEDURE Read(VAR w: WORD);
PROCEDURE ReadBlock(a:ADDRESS;length:CARDINAL);
PROCEDURE Write(ch: CHAR);
PROCEDURE WriteLn;
PROCEDURE WriteString(VAR str: ARRAY OF CHAR);
PROCEDURE WriteBlanks(n: INTEGER);
PROCEDURE WriteHex(x: CARDINAL; l: INTEGER);
PROCEDURE WriteHexAdr(x: ADDRESS; l: INTEGER);
PROCEDURE WriteCard(x: CARDINAL; l: INTEGER);
PROCEDURE WriteInt(x,l: INTEGER);
PROCEDURE WriteDigit(x: CARDINAL);
END DecIO.
!Funky!Stuff!
echo x - Disasm.DEF
cat >Disasm.DEF <<'!Funky!Stuff!'
DEFINITION MODULE Disasm;
FROM SYSTEM IMPORT ADDRESS;
EXPORT QUALIFIED Disassemble,ReadCount;
VAR
ReadCount: CARDINAL;
PROCEDURE Disassemble(data:ADDRESS;loadpoint,maxbyte:CARDINAL);
END Disasm.
!Funky!Stuff!
echo x - DecIO.MOD
cat >DecIO.MOD <<'!Funky!Stuff!'
IMPLEMENTATION MODULE DecIO;
FROM M2Files IMPORT Open,Create,Close,File,
ReadWord, WriteChar, eolc;
FROM SYSTEM IMPORT
ADDRESS,WORD;
IMPORT Terminal;
IMPORT Conversions;
FROM QuickDraw IMPORT Str255;
FROM PascalStrings IMPORT MakePascalString, MakeModulaString;
FROM SFpackage IMPORT SFGetFile,SFPutFile,SFReply,SFTypeList;
(*
* EXPORT WriteHex,WriteHexAdr,WriteCard,WriteInt,WriteDigit,
* checksum,printChecksum,ErrorMessage,StartIO,EndIO,
* Read,ReadBlock,Write,WriteLn,WriteString,
* WriteBlanks,WriteNumbers,LinkStream;
*)
VAR
Column:CARDINAL;
PROCEDURE ErrorMessage(VAR str: ARRAY OF CHAR);
BEGIN
Terminal.WriteString(str);
Terminal.WriteLn;
END ErrorMessage;
PROCEDURE StartIO(VAR found:BOOLEAN);
VAR
FileName: ARRAY [0..50] OF CHAR;
optError : BOOLEAN;
length, i : CARDINAL;
reply : BOOLEAN;
ch : CHAR;
List: SFTypeList;
MPrompt: Str255;
REPLY: SFReply;
BEGIN
Column := 0;
found := FALSE;
printChecksum := TRUE;
optError := FALSE;
i := 1;
MakePascalString('Open What Link File?',MPrompt);
List[1] := 'LNK ';
(* Because the compiler is not consistant with the
* file type this is not used!!
*)
SFGetFile(100,100,MPrompt,ADDRESS(0),0,List,ADDRESS(0),REPLY);
Terminal.ClearTerminal;
IF (REPLY.good) THEN
MakeModulaString(REPLY.fName,FileName);
Open(LinkStream,FileName,TRUE,found);
IF found THEN
i := 0;
WHILE (FileName[i] # 0C) AND (FileName[i] # '.') DO
INC(i)
END;
FileName[i+1] := 'D';
FileName[i+2] := 'E';
FileName[i+3] := 'C';
FileName[i+4] := 0C;
Create(decStream, FileName, found);
IF NOT found THEN
Terminal.WriteString(' ---- file not created');
Terminal.WriteLn
END
ELSE
Terminal.WriteString(FileName);
Terminal.WriteString(' ---- file not found');
Terminal.WriteLn
END
ELSE
Terminal.WriteString(' ---- filename required on command line');
Terminal.WriteLn
END
END StartIO;
PROCEDURE EndIO;
VAR
Done: BOOLEAN;
BEGIN
Close(decStream,Done);
Close(LinkStream,Done);
END EndIO;
PROCEDURE TabTo(col:CARDINAL);
BEGIN
IF (Column < col) THEN
WriteBlanks(col - Column)
END
END TabTo;
PROCEDURE Read(VAR w: WORD);
BEGIN
ReadWord(LinkStream,w);
(*$T-*) INC(checksum,CARDINAL(w)); (*$T=*)
END Read;
PROCEDURE ReadBlock(a:ADDRESS; length:CARDINAL);
VAR
i: CARDINAL;
w: WORD;
a1: ADDRESS;
BEGIN
FOR i := 0 TO (length - 2) BY 2 DO
Read(w);
a1 := (a + ADDRESS(i));
a1^ := w
END
END ReadBlock;
PROCEDURE Write(ch: CHAR);
BEGIN
WriteChar(decStream,ch);
INC(Column);
IF Column >= 80 THEN
WriteLn
END
END Write;
PROCEDURE WriteLn;
BEGIN
WriteChar(decStream,eolc);
Column := 0
END WriteLn;
PROCEDURE WriteString(VAR str: ARRAY OF CHAR);
VAR k: CARDINAL;
BEGIN
k := 0;
WHILE (k <= HIGH(str)) AND (str[k] <> 0C) DO
Write(str[k]); INC(k)
END;
END WriteString;
PROCEDURE WriteBlanks(n: INTEGER);
BEGIN
WHILE n > 0 DO
DEC(n);
Write(' ')
END
END WriteBlanks;
PROCEDURE WriteHex(x: CARDINAL; l: INTEGER);
VAR
String: ARRAY [0..16] OF CHAR;
BEGIN
Conversions.ConvertHex(x,l,String);
WriteString(String);
IF Column >= 80 THEN WriteLn END;
END WriteHex;
PROCEDURE WriteHexAdr(x: ADDRESS; l: INTEGER);
VAR
String: ARRAY [0..16] OF CHAR;
BEGIN
Conversions.ConvertAddrHex(x,l,String);
WriteString(String);
IF Column >= 80 THEN WriteLn END;
END WriteHexAdr;
PROCEDURE WriteCard(x: CARDINAL; l: INTEGER);
VAR
String: ARRAY [0..16] OF CHAR;
BEGIN
Conversions.ConvertCardinal(x,l,String);
WriteString(String);
IF Column >= 80 THEN WriteLn END;
END WriteCard;
PROCEDURE WriteInt(x,l: INTEGER);
VAR
String: ARRAY [0..16] OF CHAR;
BEGIN
Conversions.ConvertInteger(x,l,String);
WriteString(String);
IF Column >= 80 THEN WriteLn END;
END WriteInt;
PROCEDURE WriteDigit(x: CARDINAL);
BEGIN
Write(CHR(x + 60B));
IF Column >= 80 THEN WriteLn END;
END WriteDigit;
BEGIN
checksum := 0
END DecIO.
!Funky!Stuff!
echo x - DecLink.MOD
cat >DecLink.MOD <<'!Funky!Stuff!'
(*****************************************
* *
* The Following Code is Derived from *
* A Hardcopy printout of *
******************************************
* D E C O D E *
* *
* for PDP11 MODULA-2 compiler. *
* *
* Decodes MODULA-2 Load files *
* (extension .LOD). *
* *
* Version of 19.03.80 *
* Unix version 19.05.81 *
* *
* Institut fuer Informatik *
* ETH-Zentrum *
* CH-8092 Zuerich *
* *
* Derived from DECODE for MODULA-2 *
* link files (extension .LNK). *
******************************************
* Details of the link file were *
* Derived from a Hardcopy of the *
* Code for Pass Five of the PDP-11 *
* Modula-2 Compiler *
******************************************
* This code is *
* Version of 09/10/85 *
*****************************************)
MODULE DecLink;
IMPORT SYSTEM;
IMPORT DecIO;
IMPORT M2Files,Terminal,QuickDraw,PascalStrings;
FROM DecIO IMPORT StartIO,EndIO;
IMPORT Storage;
IMPORT Disasm;
MODULE Binary;
FROM DecIO IMPORT
Read,Write,WriteHex,WriteBlanks,WriteString,WriteLn;
FROM SYSTEM IMPORT ADDRESS;
EXPORT NoDecode,StringDecode;
PROCEDURE LineHeader(ic,Linkpoint: CARDINAL);
BEGIN
WriteHex(ic,4);
IF Linkpoint <> 0 THEN
Write(':');
WriteHex(Linkpoint + ic,4)
ELSE
WriteBlanks(5)
END
END LineHeader;
PROCEDURE NoDecode(Linkpoint,maxbyte: CARDINAL);
VAR
ic,printed,w: CARDINAL;
BEGIN
WriteString('NO DECODE -------- ');
WriteString('DATA');
ic := 0;
printed := 16;
WHILE ic < maxbyte DO
IF printed = 16 THEN
printed := 0;
WriteLn;
LineHeader(ic,Linkpoint);
Write(' ')
END;
Read(w);
WriteHex(w,5);
INC(ic,2);
INC(printed)
END;
WriteLn;
END NoDecode;
PROCEDURE WriteAsChar(w:CARDINAL);
VAR
c1,c2: CHAR;
BEGIN
c1 := CHR(w DIV 400B);
IF c1 # 0C THEN
Write(c1)
ELSE
Write('.')
END;
c2 := CHR(w MOD 400B);
IF c2 <> 0C THEN
Write(c2)
ELSE
Write('.')
END
END WriteAsChar;
PROCEDURE StringDecode(Linkpoint,maxbyte: CARDINAL);
VAR
ic,printed,w: CARDINAL;
BEGIN
WriteString('STRING DECODE -------- ');
WriteString('CONSTANTS');
ic := 0;
printed := 32;
WHILE ic < maxbyte DO
IF printed = 32 THEN
printed := 0;
WriteLn;
LineHeader(ic,Linkpoint);
Write(' ')
END;
Read(w);
WriteAsChar(w);
INC(ic,2);
INC(printed)
END;
WriteLn;
END StringDecode;
END Binary;
MODULE DecodeLinkFormat;
FROM SYSTEM IMPORT ADDRESS;
IMPORT Terminal,NoDecode,StringDecode;
FROM M2Files IMPORT EndFile;
FROM DecIO IMPORT checksum,printChecksum,ErrorMessage,
Read,ReadBlock,Write,WriteLn,WriteString,
WriteBlanks,LinkStream,
WriteHex,WriteHexAdr,WriteCard,
WriteInt,WriteDigit,TabTo;
FROM Disasm IMPORT Disassemble,ReadCount;
FROM Storage IMPORT ALLOCATE,DEALLOCATE;
EXPORT InitFlagNames,LinkDecoder;
TYPE FlagType =
(SCModHeader,ImportElement,DataSize,FilledData,
ProcCode,InitCode,SCModInitCode,ExcpCode (**),
RefOwnData,RefExtData,RefOwnCode(**),
RefOwnProcCall,RefExtProcCall,
RefOwnProcAss,RefExtProcAss,
RefOwnExcp (**),RefExtExcp(**),RefExtInitCall,
SCModEnd,LinkCodeVersion,
(*extension used by compiler only:*)
RefAnyProcCall,RefAnyProcAss,
(* New 68000 Flags *)
StringData,Sym17,
RefStrData,Sym19,RefSysProcCall
);
(**) (* Directives marked with such an empty comment
are not output of the compiler up to now.*)
CONST modnamlength = 24;
VAR flagName: ARRAY FlagType,[0..32] OF CHAR;
PROCEDURE GetWriteModuleName;
VAR k,l: CARDINAL;
ch: CHAR;
print: BOOLEAN;
BEGIN
l := 0;
print := TRUE;
REPEAT
Read(k);
INC(l);
IF print THEN
ch := CHR(k DIV 400B);
IF ch # 0C THEN
Write(ch)
ELSE
print := FALSE
END
END;
IF print THEN
ch := CHR(k MOD 400B);
IF ch <> 0C THEN
Write(ch)
ELSE
print := FALSE
END
END;
UNTIL l >= modnamlength DIV 2;
END GetWriteModuleName;
PROCEDURE GetWriteHex(VAR k: CARDINAL);
BEGIN
Read(k);
WriteHex(k,5);
END GetWriteHex;
PROCEDURE GetWriteAddress(VAR x: ADDRESS);
VAR k:RECORD
CASE INTEGER OF
0: a: ADDRESS
| 1: w: ARRAY [0..1] OF CARDINAL;
END
END;
BEGIN
Read(k.w[0]);
Read(k.w[1]);
WriteHexAdr(k.a,9);
x := k.a
END GetWriteAddress;
PROCEDURE GetWriteLength(VAR length: CARDINAL);
BEGIN
Read(length);
WriteString(', number of bytes = ');
WriteCard(length,0);
END GetWriteLength;
PROCEDURE GetWriteChecksum;
VAR savechecksum,lchecksum: CARDINAL;
BEGIN
savechecksum := checksum;
Read(lchecksum);
(*
* WriteString(' checksum:');
* IF printChecksum THEN
* WriteHex(lchecksum,5);
* END;
*)
IF savechecksum # lchecksum THEN
WriteString(' checksum:');
IF printChecksum THEN
WriteHex(lchecksum,5);
END;
WriteString(' ----- error -----');
IF printChecksum THEN
WriteHex(savechecksum,5)
END;
WriteLn
END;
checksum := savechecksum
END GetWriteChecksum;
PROCEDURE InitFlagNames;
BEGIN
flagName[SCModHeader] := 'Module Header';
flagName[ImportElement] := 'Import';
flagName[DataSize] := 'Data Size';
flagName[FilledData] := 'Filled Data';
flagName[ProcCode] := 'Procedure Code';
flagName[InitCode] := 'Init Code';
flagName[SCModInitCode] := 'Init Code For Module';
flagName[ExcpCode] := 'Unused ExcpCode';
flagName[RefOwnData] := 'Own Data';
flagName[RefExtData] := 'Extern Data';
flagName[RefOwnCode] := 'Own Code';
flagName[RefOwnProcCall] := 'Own Proc Call';
flagName[RefExtProcCall] := 'Extern Proc Call';
flagName[RefOwnProcAss] := 'Own Proc Ass';
flagName[RefExtProcAss] := 'Extern Proc Ass';
flagName[RefOwnExcp] := 'Own Excp';
flagName[RefExtExcp] := 'Extern Excp';
flagName[RefExtInitCall] := 'Extern Init Call';
flagName[SCModEnd] := 'SC Module End';
flagName[LinkCodeVersion] := 'Link Code Version';
flagName[RefAnyProcCall] := 'Any Proc Call';
flagName[RefAnyProcAss] := 'Any Proc Ass';
flagName[StringData] := 'StringData';
flagName[Sym17] := 'Unknown Sym 17';
flagName[RefStrData] := 'String Data';
flagName[Sym19] := 'Unknown Sym 19';
flagName[RefSysProcCall] := 'System Proc Call'
END InitFlagNames;
TYPE
JumpTable = RECORD
Addr,Len,Link: CARDINAL
END;
VAR
DataBlock: ADDRESS;
HasBlock: BOOLEAN;
Current,Length: CARDINAL;
JumpTables: ARRAY [0..14] OF JumpTable;
NumJumpTables: CARDINAL;
PROCEDURE AddJumpTable(address,length,linkpoint:CARDINAL);
VAR
I,J: CARDINAL;
BEGIN
WITH JumpTables[NumJumpTables] DO
Addr := address;
Len := length;
Link := linkpoint;
INC(NumJumpTables)
END
END AddJumpTable;
PROCEDURE DecodeJumpTable(j:JumpTable);
VAR
a: ADDRESS;
i: CARDINAL;
v: CARDINAL;
BEGIN
WriteString("JumpTable");
WriteLn;
FOR i := 0 TO j.Len DO (* Len + 1 == Default case *)
a := DataBlock + ADDRESS((i * 2) + j.Addr);
v := CARDINAL(a^);
TabTo(18);
WriteHex(v,4);
WriteString(' {');
WriteHex(v + j.Link,4);
Write('}');
WriteLn;
END;
Current := j.Addr + (j.Len * 2) + 2; (* 2 for 0 case *)
END DecodeJumpTable;
PROCEDURE DecodeTo(LinkPoint:CARDINAL);
VAR
I: CARDINAL;
a: ADDRESS;
BEGIN
IF LinkPoint >= Length THEN RETURN END;
IF NumJumpTables > 0 THEN
FOR I := NumJumpTables -1 TO 0 BY -1 DO
WITH JumpTables[I] DO
IF Addr < LinkPoint THEN
a := DataBlock + ADDRESS(Current);
Disassemble(a,Current,Addr - Current);
DecodeJumpTable(JumpTables[I]);
DEC(NumJumpTables)
END
END
END
END;
a := DataBlock + ADDRESS(Current);
Disassemble(a,Current,LinkPoint - Current + 2);
Current := Current + ReadCount
END DecodeTo;
PROCEDURE DecodeCase(LinkPoint:CARDINAL);
VAR
a: ADDRESS;
v,len: CARDINAL;
BEGIN
DecodeTo(LinkPoint + 2);
TabTo(9);
WriteString('SYSTEM CALL CASE');
WriteLn;
WriteString('Min Value: ');
a := DataBlock + ADDRESS(LinkPoint + 4);
v := CARDINAL(a^);
WriteHex(v,4);
a := DataBlock + ADDRESS(LinkPoint + 6);
v := CARDINAL(a^);
WriteHex(v,4);
WriteString(' Number of Cases: ');
a := DataBlock + ADDRESS(LinkPoint + 8);
len := CARDINAL(a^);
WriteHex(len,4);
a := DataBlock + ADDRESS(LinkPoint + 10);
len := CARDINAL(a^);
WriteHex(len,4);
WriteString(" Jump Table Offset: ");
a := DataBlock + ADDRESS(LinkPoint + 12);
v := CARDINAL(a^);
WriteHex(v,4);
a := DataBlock + ADDRESS(LinkPoint + 14);
v := CARDINAL(a^);
WriteHex(v,4);
Current := Current + 12;
AddJumpTable(LinkPoint + 4 + v,len,LinkPoint + 4)
END DecodeCase;
PROCEDURE LinkDecoder;
VAR
flag: FlagType;
k,i: CARDINAL;
savechecksum,lchecksum: CARDINAL;
ok: BOOLEAN;
BEGIN
WriteString('Link key = ');
GetWriteHex(k);
WriteString(', LinkCodeKey & LinkFileKey = ');
GetWriteHex(k);
WriteLn;
GetWriteChecksum;
ok := TRUE;
HasBlock := FALSE;
NumJumpTables := 0;
LOOP
IF NOT ok THEN EXIT END;
Read(k);
IF EndFile(LinkStream) THEN EXIT END;
WriteLn;
IF k <= ORD(RefSysProcCall) THEN
flag := VAL(FlagType,k);
Terminal.WriteString(flagName[flag]);
Terminal.WriteLn;
CASE flag OF
SCModHeader:
WriteString(flagName[flag]);
WriteString(' : ');
GetWriteModuleName;
WriteLn;
WriteString('key = ');
GetWriteHex(k);
GetWriteHex(k);
GetWriteHex(k);
| ImportElement:
WriteString(flagName[flag]);
WriteString(' : ');
GetWriteModuleName;
WriteString(', Key = ');
GetWriteHex(k);
GetWriteHex(k);
GetWriteHex(k);
WriteString(', Module Number = ');
GetWriteHex(k);
| DataSize:
WriteString(flagName[flag]);
WriteString(' : ');
GetWriteHex(k);
| FilledData:
WriteString(flagName[flag]);
WriteString(' Relative Start Address = ');
GetWriteHex(k);
GetWriteLength(Length);
WriteLn;
NoDecode(k,Length)
| ProcCode, InitCode, SCModInitCode,SCModEnd:
IF HasBlock THEN
DecodeTo(Length - 2);
DEALLOCATE(DataBlock,Length)
END;
IF flag = SCModEnd THEN
RETURN
END;
WriteLn;
WriteString(flagName[flag]);
WriteString(' Proc # ');
Read(k);
WriteCard(k,0);
WriteLn;
WriteString(' Entry Point ');
GetWriteHex(k);
IF flag = SCModInitCode THEN
WriteString(' First Code (after Init) ');
GetWriteHex(i)
END;
GetWriteLength(Length);
ALLOCATE(DataBlock,Length);
ReadBlock(DataBlock,Length);
HasBlock := TRUE;
Current := 0;
| ExcpCode:
WriteString(flagName[flag]);
WriteString(' Found ExcpCode Error');
ok := FALSE
| RefOwnData, RefStrData:
Read(k);
DecodeTo(k + 2);
TabTo(9);
WriteString(flagName[flag]);
| RefExtData:
Read(k);
DecodeTo(k + 2);
TabTo(9);
WriteString(flagName[flag]);
WriteString(' Module # ');
Read(k);
WriteCard(k,0)
| RefOwnCode:
WriteString(flagName[flag]);
WriteString('Error Found RefOwnCode');
ok := FALSE
| RefOwnProcCall,RefOwnProcAss:
Read(k);
DecodeTo(k + 2);
TabTo(9);
WriteString(flagName[flag]);
WriteString(' Proc # ');
Read(k);
WriteCard(k,0)
| RefExtProcCall,RefExtProcAss:
Read(k);
DecodeTo(k + 2);
TabTo(9);
WriteString(flagName[flag]);
WriteString(' Proc # ');
Read(k);
WriteCard(k,0);
WriteString(' Module # ');
Read(k);
WriteCard(k,0)
| RefOwnExcp,RefExtExcp:
WriteString(flagName[flag]);
WriteString(' Error');
ok := FALSE
| RefExtInitCall:
Read(k);
DecodeTo(k + 2);
TabTo(9);
WriteString(flagName[flag]);
| LinkCodeVersion:
WriteString(flagName[flag]);
WriteString(" I don't know why it's just here.");
WriteLn
| StringData:
WriteString(flagName[flag]);
GetWriteLength(Length);
WriteLn;
StringDecode(0,Length)
| Sym17,Sym19:
WriteString(flagName[flag]);
IF EndFile(LinkStream) THEN
ok := FALSE;
EXIT
END;
REPEAT
savechecksum := checksum;
Read(lchecksum);
IF EndFile(LinkStream) THEN
ok := FALSE;
END;
IF savechecksum # lchecksum THEN
WriteHex(lchecksum,5)
END;
UNTIL (ok = FALSE) OR (savechecksum = lchecksum);
checksum := savechecksum
| RefSysProcCall:
Read(k);
Read(i);
IF i = 1 THEN (* SYSTEM CODE IS CASE *);
DecodeCase(k);
ELSE
DecodeTo(k + 2);
TabTo(9);
WriteString(flagName[flag]);
WriteString(' Proc # ');
WriteCard(i,0);
END
END (*CASE*);
GetWriteChecksum;
ELSE
Terminal.WriteString('Found Unknown Key ');
Terminal.WriteLn;
WriteString('Found Key ');
WriteHex(k,5);
IF EndFile(LinkStream) THEN
ok := FALSE;
EXIT
END;
REPEAT
savechecksum := checksum;
Read(lchecksum);
IF EndFile(LinkStream) THEN
ok := FALSE;
END;
IF savechecksum # lchecksum THEN
WriteHex(lchecksum,5)
END;
UNTIL (ok = FALSE) OR (savechecksum = lchecksum);
checksum := savechecksum;
END;
END (*LOOP*);
IF NOT ok THEN
Terminal.WriteString('---- wrong format');
Terminal.WriteLn;
WriteString('---- wrong format');
WriteLn;
END
END LinkDecoder;
END DecodeLinkFormat;
VAR found: BOOLEAN;
BEGIN (*DecLink*)
StartIO(found);
IF found THEN
InitFlagNames;
LinkDecoder;
EndIO;
END
END DecLink.
!Funky!Stuff!
echo x - Disasm.MOD
cat >Disasm.MOD <<'!Funky!Stuff!'
(*
* The Following Code is Free to any one who cares to use it, provided
* that they are willing to pass it on to any one else who wishes it.
*
* Bob Campbell, Kirkland Wa (uw-beaver!tikal!bobc).
*
* The code that follows is a crude implementation of a Motorola 68000
* Disassembler, it can disassemble illegal op codes mostly with respect
* to addressing modes which are not valid. (MOVE.B #'a',A0 etc).
*
* The code breaks the instruction up into line codes (as in "LINE 1010"
* or in mac terms "A-LINE" Trap). This is done based on the first
* nibble there are then routines for Line0,Line4-Line9,LineB-LineE.
* Line1 Line2 and Line3 are move instructions and are handled by
* DecMove, LineA and LineF are traps and are printed out as such
* in the main routine.
*
* Version of 09/10/85
*
*)
IMPLEMENTATION MODULE Disasm;
FROM SYSTEM IMPORT WORD,ASH,ADDRESS;
IMPORT DecIO;
IMPORT Terminal,OutTerminal;
FROM DecIO IMPORT Write,WriteLn,WriteString,
WriteHex,WriteInt,WriteCard,TabTo;
(*
* EXPORT QUALIFIED Disassemble;
*)
VAR (* ReadCount:CARDINAL; for Telling when done *)
WordsUsed: ARRAY[0..15] OF CARDINAL;
WordCount,LoadOffset: CARDINAL;
DataPointer: ADDRESS;
(*
* Read a Word and save the value in WordsUsed (until printed).
*)
PROCEDURE Read(VAR I:WORD);
BEGIN
ReadCount := ReadCount + 2;
I := DataPointer^;
INC(DataPointer,2);
WordsUsed[WordCount] := CARDINAL(I);
INC(WordCount)
END Read;
(*
* Write Effective Address
* The parameter IsLong is only used for mode 7 register 4.
*)
PROCEDURE WriteEA(Mode,Reg:CARDINAL;IsLong:BOOLEAN);
VAR
Data,Index,Disp:CARDINAL;
LongIndex,AddressReg: BOOLEAN;
BEGIN
CASE Mode OF
0: (* Dn *)
Write('D');
WriteCard(Reg,0)
| 1: (* An *)
Write('A');
WriteCard(Reg,0)
| 2: (* (An) *)
WriteString('(A');
WriteCard(Reg,0);
Write(')')
| 3: (* (An)+ *)
WriteString('(A');
WriteCard(Reg,0);
WriteString(')+')
| 4: (* -(An) *)
WriteString('-(A');
WriteCard(Reg,0);
Write(')')
| 5: (* d(An) *)
Read(Data);
WriteHex(Data,4);
WriteString('(A');
WriteCard(Reg,0);
Write(')')
| 6: (* d(An,Xi) *)
Read(Data);
Index := ASH(Data,-12) MOD 8;
AddressReg := (15 IN BITSET(Data));
LongIndex := (11 IN BITSET(Data));
Disp := Data MOD 256;
WriteHex(Disp,2);
WriteString('(A');
WriteCard(Reg,0);
IF AddressReg THEN
WriteString(',A')
ELSE
WriteString(',D')
END (*IF*);
WriteCard(Index,0);
IF LongIndex THEN
WriteString('.W)')
ELSE
WriteString('.L)')
END
| 7:
CASE Reg OF
0: (* Abs.W *)
Read(Data);
WriteHex(Data,4);
| 1: (* Abs.L *)
Read(Data);
WriteHex(Data,4);
Read(Data);
WriteHex(Data,4);
| 2: (* d(PC) *)
Read(Data);
WriteHex(Data,4);
WriteString('(PC)');
WriteString(' {');
WriteHex(Data + ReadCount + LoadOffset - 2,4);
Write('}')
| 3: (* d(PC,Xi) *)
Read(Data);
Index := ASH(Data,-12) MOD 8;
AddressReg := (15 IN BITSET(Data));
LongIndex := (11 IN BITSET(Data));
Disp := Data MOD 256;
WriteHex(Disp,2);
WriteString('(PC');
IF AddressReg THEN
WriteString(',A')
ELSE
WriteString(',D')
END (*IF*);
WriteCard(Index,0);
IF LongIndex THEN
WriteString('.W)')
ELSE
WriteString('.L)')
END;
WriteString(' {');
WriteHex(Disp + ReadCount + LoadOffset - 2,4);
WriteString('(Xi)}')
| 4: (* #data *)
Read(Data);
Write('#');
WriteHex(Data,4);
IF IsLong THEN
Read(Data);
WriteHex(Data,4)
END (*IF*)
END (*CASE*)
ELSE
WriteCard(Mode,1);
END (*CASE*)
END WriteEA;
PROCEDURE Write1EA(Mode1,Reg1:CARDINAL;Long:BOOLEAN);
BEGIN
TabTo(18);
WriteEA(Mode1,Reg1,Long);
END Write1EA;
PROCEDURE Write2EA(Mode1,Reg1,Mode2,Reg2:CARDINAL;Long:BOOLEAN);
BEGIN
Write1EA(Mode1,Reg1,Long);
Write(',');
WriteEA(Mode2,Reg2,Long)
END Write2EA;
PROCEDURE WriteMnemonic(VAR Str:ARRAY OF CHAR; Length:CARDINAL);
BEGIN
WriteString(Str);
CASE Length OF
0:
WriteString(".B")
| 1:
WriteString(".W")
| 2:
WriteString(".L")
END (*CASE*)
END WriteMnemonic;
PROCEDURE WriteData(Inst:CARDINAL);
BEGIN
WriteString("DATA");
TabTo(10);
WriteHex(Inst,4)
END WriteData;
PROCEDURE WriteRegList(First,Last:CARDINAL;PreDec:BOOLEAN);
VAR
FirstRegNum,LastRegNum,RegType:CARDINAL;
BEGIN
IF PreDec THEN
FirstRegNum := 15 - First;
LastRegNum := 15 - Last
ELSE
FirstRegNum := First;
LastRegNum := Last
END;
WriteEA(ASH(FirstRegNum,-3),FirstRegNum MOD 8,FALSE);
IF (First # Last) THEN
Write('-');
WriteEA(ASH(LastRegNum,-3),LastRegNum MOD 8,FALSE);
END
END WriteRegList;
PROCEDURE WriteRegMask(Mask:CARDINAL;PreDec:BOOLEAN);
VAR
Regs:BITSET;
First,Last,I:CARDINAL;
FoundOne,NeedComma:BOOLEAN;
BEGIN
Regs := BITSET(Mask);
FoundOne := FALSE;
NeedComma := FALSE;
FOR I := 0 TO 15 DO
IF I IN Regs THEN
IF FoundOne THEN
Last := I
ELSE
First := I;
Last := I;
FoundOne := TRUE
END (*IF*)
ELSE
IF FoundOne THEN
IF NeedComma THEN Write(',') END;
WriteRegList(First,Last,PreDec);
FoundOne := FALSE;
NeedComma := TRUE
END
END
END (*FOR*);
IF FoundOne THEN
IF NeedComma THEN Write(',') END;
WriteRegList(First,Last,PreDec);
END (*IF*)
END WriteRegMask;
PROCEDURE WriteCC(Cond:CARDINAL);
BEGIN
CASE Cond OF
0:
WriteString('T ')
| 1:
WriteString('F ')
| 2:
WriteString('HI')
| 3:
WriteString('LS')
| 4:
WriteString('CC')
| 5:
WriteString('CS')
| 6:
WriteString('NE')
| 7:
WriteString('EQ')
| 8:
WriteString('VC')
| 9:
WriteString('VS')
| 0AH:
WriteString('PI')
| 0BH:
WriteString('MI')
| 0CH:
WriteString('GE')
| 0DH:
WriteString('LT')
| 0EH:
WriteString('GT')
| 0FH:
WriteString('LE')
END (*CASE*)
END WriteCC;
PROCEDURE Line0(Inst:CARDINAL);
VAR
Nibble,Size,Mode,Register,Data:CARDINAL;
BEGIN
Nibble := ASH(Inst,-8) MOD 16;
Size := ASH(Inst,-6) MOD 4;
Mode := ASH(Inst,-3) MOD 8;
Register:= Inst MOD 8;
IF ODD(Nibble) THEN (* MOVEP or BIT *)
IF (Mode = 1) THEN
WriteMnemonic('MOVEP',(Size MOD 2) + 1);
IF (Size = 0) OR (Size = 1) THEN
Write2EA(5,Register,0,Nibble DIV 2,FALSE)
ELSE
Write2EA(0,Nibble DIV 2,5,Register,FALSE)
END (* IF *)
ELSIF (Mode = 7) AND (Register > 1) THEN
WriteData(Inst);
ELSE (* DYNAMIC BIT *)
Write('B');
CASE Size OF
0:
WriteString('TST')
| 1:
WriteString('CHG')
| 2:
WriteString('CLR')
| 3:
WriteString('SET')
END (*CASE*);
Write2EA(0,Nibble DIV 2,Mode,Register,FALSE)
END
ELSIF ((Nibble # 8) AND (Size = 3)) OR
((Mode = 7) AND (Register > 1)) THEN
WriteData(Inst);
ELSE
CASE Nibble OF
0:
WriteMnemonic('ORI',Size)
| 2:
WriteMnemonic('ANDI',Size)
| 4:
WriteMnemonic('SUBI',Size)
| 6:
WriteMnemonic('ADDI',Size)
| 8:
Write('B');
CASE Size OF
0:
WriteString('TST')
| 1:
WriteString('CHG')
| 2:
WriteString('CLR')
| 3:
WriteString('SET')
END (*CASE*)
| 10:
WriteMnemonic('EORI',Size)
| 12:
WriteMnemonic('CMPI',Size)
| 14:
WriteMnemonic('MOVES',Size)
END; (*CASE*)
IF (Mode = 7) AND (Register = 4) THEN
Write1EA(7,4,(Nibble # 8) AND (Size = 2));
Write(',');
IF Size = 0 THEN
WriteString('CCR')
ELSIF Size = 1 THEN
WriteString('SR')
ELSE
WriteString('BAD')
END
ELSE
Write2EA(7,4,Mode,Register,(Nibble # 8) AND (Size = 2))
END (*IF*)
END (*IF*)
END Line0;
PROCEDURE DecMove(Inst:CARDINAL);
VAR
Size,DReg,SReg,DMode,SMode:CARDINAL;
BEGIN
Size := ASH(Inst,-12);
IF Size # 2 THEN
Size := ASH(Size,-1)
END;
DReg := ASH(Inst,-9) MOD 8;
DMode := ASH(Inst,-6) MOD 8;
SMode := ASH(Inst,-3) MOD 8;
SReg := Inst MOD 8;
IF ((SMode = 7) AND (SReg > 4)) OR ((DMode = 7) AND (DReg > 1)) THEN
WriteData(Inst)
ELSE
IF (DMode = 1) THEN
WriteMnemonic('MOVEA',Size)
ELSE
WriteMnemonic('MOVE',Size)
END (*IF*);
Write2EA(SMode,SReg,DMode,DReg,Size = 2)
END (*IF*)
END DecMove;
PROCEDURE Line4(Inst:CARDINAL);
VAR
Nibble1,Nibble2,Nibble3:CARDINAL;
Size,Mode,Reg,Data:CARDINAL;
BEGIN
Nibble1 := ASH(Inst,-8) MOD 16;
Nibble2 := ASH(Inst,-4) MOD 16;
Nibble3 := Inst MOD 16;
Size := ASH(Nibble2,-2) MOD 4;
Mode := ASH(Inst,-3) MOD 8;
Reg := Inst MOD 8;
IF Nibble1 = 0EH THEN
CASE Nibble2 OF
0,1,2,3:
WriteData(Inst);
| 4:
WriteString('TRAP ');
WriteHex(Nibble3,1)
| 5:
IF Mode = 2 THEN
WriteString('LINK');
TabTo(18);
Write2EA(1,Reg,7,4,FALSE)
ELSE
WriteString('UNLK ');
TabTo(18);
Write1EA(1,Reg,FALSE)
END
| 6:
IF Nibble3 = 0 THEN
WriteString('RESET')
ELSE
WriteString('MOVE.L');
IF Mode = 4 THEN
Write1EA(1,Reg,TRUE);
WriteString(',USP')
ELSE
TabTo(18);
WriteString('USP,');
WriteEA(1,Reg,TRUE)
END (*IF*)
END
| 7:
CASE Nibble3 OF
1:
WriteString('NOP')
| 2:
WriteString('STOP')
| 3:
WriteString('RTE')
| 4:
WriteString('RTD')
| 5:
WriteString('RTS')
| 6:
WriteString('TRAPV')
| 7:
WriteString('RTR')
| 8,9,0AH,0BH,0CH,0DH,0EH,0FH:
WriteData(Inst)
END (* CASE *)
| 8,9,10,11:
WriteString('JSR');
Write1EA(Mode,Reg,FALSE)
ELSE (* 12 13 14 15 *)
WriteString('JMP');
Write1EA(Mode,Reg,FALSE)
END (* CASE *);
ELSIF Nibble1 = 8 THEN
IF Nibble2 = 4 THEN
WriteString('SWAP');
Write1EA(0,Reg,FALSE)
ELSIF Nibble2 = 8 THEN
WriteString('EXT.W');
Write1EA(0,Reg,FALSE)
ELSIF Nibble2 = 0CH THEN
WriteString('EXT.L');
Write1EA(0,Reg,FALSE)
ELSIF Size = 0 THEN
WriteString('NBCD');
Write1EA(Mode,Reg,FALSE)
ELSIF Size = 1 THEN
WriteString('PEA');
Write1EA(Mode,Reg,FALSE)
ELSE
WriteMnemonic('MOVEM',Size - 1);
TabTo(18);
Read(Data);
WriteRegMask(Data,Mode = 4);
Write(',');
WriteEA(Mode,Reg,Size = 3)
END (*IF*)
ELSIF Nibble1 = 0CH THEN
IF Size < 2 THEN
WriteData(Inst)
ELSE
WriteMnemonic('MOVEM',Size - 1);
TabTo(18);
Read(Data);
WriteRegMask(Data,Mode = 4);
Write(',');
WriteEA(Mode,Reg,Size = 3)
END (*IF*)
ELSIF ODD(Nibble1) THEN
IF (Size = 2) THEN
WriteString('CHK');
Write2EA(0,ASH(Nibble1,-1) MOD 8,Mode,Reg,FALSE)
ELSIF Size = 3 THEN
WriteString('LEA');
Write2EA(1,ASH(Nibble1,-1) MOD 8,Mode,Reg,FALSE)
ELSE
WriteData(Inst)
END (*IF*)
ELSIF Size = 3 THEN
CASE Nibble1 OF
0:
WriteString('MOVE.W SR,');
WriteEA(Mode,Reg,FALSE)
| 2:
WriteString('MOVE.W CCR,');
WriteEA(Mode,Reg,FALSE)
| 4:
WriteString('MOVE.W ');
WriteEA(Mode,Reg,FALSE);
WriteString(',CCR')
| 6:
WriteString('MOVE.W ');
WriteEA(Mode,Reg,FALSE);
WriteString(',SR')
| 10:
WriteString('TAS');
Write1EA(Mode,Reg,FALSE)
END (* CASE *)
ELSE
CASE Nibble1 OF
0:
WriteMnemonic('NEGX',Size)
| 2:
WriteMnemonic('CLR',Size)
| 4:
WriteMnemonic('NEG',Size)
| 6:
WriteMnemonic('NOT',Size)
| 0AH:
WriteMnemonic('TST',Size)
END (*CASE*);
Write1EA(Mode,Reg,Size = 2)
END (* IF *)
END Line4;
PROCEDURE Line5(Inst:CARDINAL);
VAR
Nibble,Size,Mode,Reg,Data:CARDINAL;
BEGIN
Nibble := ASH(Inst,-8) MOD 16;
Size := ASH(Inst,-6) MOD 4;
Mode := ASH(Inst,-3) MOD 8;
Reg := Inst MOD 8;
IF Size = 3 THEN
IF Mode = 1 THEN
WriteString('DB');
WriteCC(Nibble);
Write1EA(0,Reg,FALSE);
Write(',');
Read(Data);
WriteInt(INTEGER(Data),0);
WriteString(' {');
WriteHex(ReadCount + LoadOffset + Data - 2,4);
Write('}')
ELSE
Write('S');
WriteCC(Nibble);
Write1EA(0,Reg,FALSE)
END (*IF*)
ELSE
IF ODD(Nibble) THEN
WriteMnemonic('SUBQ',Size)
ELSE
WriteMnemonic('ADDQ',Size)
END (*IF*);
TabTo(18);
IF Nibble = 0 THEN
WriteString('#8')
ELSE
Write('#');
WriteHex(ASH(Nibble,-1),1)
END (*IF*);
Write(',');
WriteEA(Mode,Reg,Size = 2)
END (*IF*)
END Line5;
PROCEDURE Line6(Inst:CARDINAL);
VAR
Cond:CARDINAL;
Disp:INTEGER;
BEGIN
Cond := ASH(Inst,-8) MOD 16;
Disp := Inst MOD 100H;
IF Disp = 0 THEN
Read(Disp)
ELSIF Disp > 07FH THEN
Disp := INTEGER(BITSET(Disp) + BITSET(0FF00H))
END;
IF Cond = 0 THEN
WriteString('BRA')
ELSIF Cond = 1 THEN
WriteString('BSR')
ELSE
Write('B');
WriteCC(Cond)
END (*IF*);
TabTo(18);
WriteInt(Disp,0);
WriteString(' {');
WriteHex(Disp + INTEGER(ReadCount + LoadOffset),4);
Write('}')
END Line6;
PROCEDURE Line7(Inst:CARDINAL);
VAR
Reg:CARDINAL;
Data:INTEGER;
BEGIN
IF 8 IN BITSET(Inst) THEN
WriteData(Inst)
ELSE
WriteString('MOVEQ.L #');
Reg := ASH(Inst,-9) MOD 8;
Data := Inst MOD 100H;
IF Data > 07FH THEN
Data := INTEGER(BITSET(Data) + BITSET(0FF00H))
END;
WriteHex(Data,4);
Write(',');
WriteEA(0,Reg,FALSE)
END
END Line7;
PROCEDURE Line8(Inst:CARDINAL);
VAR
DReg,SReg,OMode,SMode:CARDINAL;
BEGIN
DReg := ASH(Inst,-9) MOD 8;
OMode := ASH(Inst,-6) MOD 8;
SMode := ASH(Inst,-3) MOD 8;
SReg := Inst MOD 8;
IF (OMode = 3) OR (OMode = 7) THEN
IF (OMode = 3) THEN
WriteString('DIVU.W')
ELSE
WriteString('DIVS.W')
END;
Write2EA(SMode,SReg,0,DReg,FALSE)
ELSIF (OMode = 4) AND ((SMode = 0) OR (SMode = 1)) THEN
WriteString('SBCD');
IF SMode = 0 THEN
Write2EA(0,SReg,0,DReg,FALSE)
ELSE
Write2EA(4,SReg,4,DReg,FALSE)
END (*IF*)
ELSE
WriteMnemonic('OR.B',OMode MOD 4);
IF (OMode < 4) THEN
Write2EA(SMode,SReg,0,DReg,OMode = 2);
ELSE
Write2EA(0,DReg,SMode,SReg,OMode = 6)
END
END (*IF*)
END Line8;
PROCEDURE Line9(Inst:CARDINAL);
VAR
DReg,OMode,SReg,SMode:CARDINAL;
BEGIN
DReg := ASH(Inst,-9) MOD 8;
OMode := ASH(Inst,-6) MOD 8;
SMode := ASH(Inst,-3) MOD 8;
SReg := Inst MOD 8;
IF (SMode < 2) AND (OMode > 3) AND (OMode # 7) THEN
WriteMnemonic('SUBX',OMode MOD 4);
IF SMode = 0 THEN
Write2EA(0,SReg,0,DReg,FALSE)
ELSE
Write2EA(4,SReg,4,DReg,FALSE)
END (*IF*)
ELSIF (OMode = 3) OR (OMode = 7) THEN
WriteMnemonic('SUBA',(OMode DIV 2) - 1);
Write2EA(SMode,SReg,1,DReg,OMode = 7)
ELSE
WriteMnemonic('SUB',OMode MOD 4);
IF (OMode = 0) OR (OMode = 1) OR (OMode = 2) THEN
Write2EA(SMode,SReg,0,DReg,OMode = 2)
ELSE
Write2EA(0,DReg,SMode,SReg,OMode = 6)
END (*IF*)
END (*IF*)
END Line9;
PROCEDURE LineB(Inst:CARDINAL);
VAR
DReg,OMode,SReg,SMode:CARDINAL;
BEGIN
DReg := ASH(Inst,-9) MOD 8;
OMode := ASH(Inst,-6) MOD 8;
SMode := ASH(Inst,-3) MOD 8;
SReg := Inst MOD 8;
IF (SMode = 1) AND (OMode > 3) AND (OMode # 7) THEN
WriteMnemonic('CMPM',OMode MOD 4);
Write2EA(4,SReg,4,DReg,FALSE);
ELSIF (OMode = 3) OR (OMode = 7) THEN
WriteMnemonic('CMPA',(OMode DIV 4) + 1);
Write2EA(SMode,SReg,1,DReg,OMode = 7)
ELSIF OMode > 3 THEN
WriteMnemonic('EOR',OMode MOD 4);
Write2EA(0,DReg,SMode,SReg,OMode = 6)
ELSE
WriteMnemonic('CMP',OMode);
Write2EA(SMode,SReg,0,DReg,OMode = 2)
END (*IF*)
END LineB;
PROCEDURE LineC(Inst:CARDINAL);
VAR
DReg,OMode,SReg,SMode:CARDINAL;
BEGIN
DReg := ASH(Inst,-9) MOD 8;
OMode := ASH(Inst,-6) MOD 8;
SMode := ASH(Inst,-3) MOD 8;
SReg := Inst MOD 8;
IF ((OMode = 5) AND (SMode < 2)) OR
((OMode = 6) AND (SMode = 1)) THEN
WriteString('EXG');
IF OMode = 6 THEN
Write2EA(0,DReg,1,SReg,FALSE)
ELSIF (SMode = 0) THEN
Write2EA(0,DReg,0,SReg,FALSE)
ELSE
Write2EA(1,DReg,1,SReg,FALSE)
END (*IF*);
ELSIF (OMode = 3) OR (OMode = 7) THEN
IF (OMode = 3) THEN
WriteString('MULU.W')
ELSE
WriteString('MULS.W')
END;
Write2EA(SMode,SReg,0,DReg,OMode = 7)
ELSIF (OMode = 4) AND ((SMode = 0) OR (SMode = 1)) THEN
WriteString('ABCD');
IF SMode = 0 THEN
Write2EA(0,SReg,0,DReg,FALSE)
ELSE
Write2EA(4,SReg,4,DReg,FALSE)
END (*IF*)
ELSE
WriteMnemonic('AND',OMode MOD 4);
IF (OMode < 4) THEN
Write2EA(SMode,SReg,0,DReg,OMode = 2)
ELSE
Write2EA(0,DReg,SMode,SReg,OMode = 6)
END
END (*IF*)
END LineC;
PROCEDURE LineD(Inst:CARDINAL);
VAR
DReg,OMode,SReg,SMode:CARDINAL;
BEGIN
DReg := ASH(Inst,-9) MOD 8;
OMode := ASH(Inst,-6) MOD 8;
SMode := ASH(Inst,-3) MOD 8;
SReg := Inst MOD 8;
IF (SMode < 2) AND (OMode > 3) AND (OMode # 7) THEN
WriteMnemonic('ADDX',OMode MOD 4);
IF SMode = 0 THEN
Write2EA(0,SReg,0,DReg,FALSE)
ELSE
Write2EA(4,SReg,4,DReg,FALSE)
END (*IF*)
ELSIF (OMode = 3) OR (OMode = 7) THEN
WriteString('ADDA');
IF (OMode = 3) THEN
WriteString('.W ')
ELSE
WriteString('.L ')
END;
Write2EA(SMode,SReg,1,DReg,OMode = 7)
ELSE
WriteMnemonic('ADD',OMode MOD 4);
IF (OMode = 0) OR (OMode = 1) OR (OMode = 2) THEN
Write2EA(SMode,SReg,0,DReg,OMode = 2)
ELSE
Write2EA(0,DReg,SMode,SReg,OMode = 6)
END (*IF*)
END (*IF*)
END LineD;
PROCEDURE LineE(Inst:CARDINAL);
VAR
Count,Size,Type,Mode,Reg:CARDINAL;
Left:BOOLEAN;
BEGIN
Size := ASH(Inst,-6) MOD 4;
Reg := Inst MOD 8;
Left := (ASH(Inst,-8) MOD 2) = 1;
IF Size = 3 THEN
Type := ASH(Inst,-9) MOD 4;
Mode := ASH(Inst,-3) MOD 8;
CASE Type OF
0:
IF (Left) THEN
WriteString('ASL.W')
ELSE
WriteString('ASR.W')
END (*IF*)
| 1:
IF (Left) THEN
WriteString('LSL.W')
ELSE
WriteString('LSR.W')
END
| 2:
IF (Left) THEN
WriteString('ROXL.W')
ELSE
WriteString('ROXR.W')
END
| 3:
IF Left THEN
WriteString('ROL.W')
ELSE
WriteString('ROR.W')
END
END (*CASE*);
Write1EA(Mode,Reg,FALSE)
ELSE
Count := ASH(Inst,-9) MOD 8;
Size := ASH(Inst,-6) MOD 4;
Type := ASH(Inst,-3) MOD 4;
CASE Type OF
0:
IF (Left) THEN
WriteMnemonic('ASL',Size)
ELSE
WriteMnemonic('ASR',Size)
END (*IF*)
| 1:
IF (Left) THEN
WriteMnemonic('LSL',Size)
ELSE
WriteMnemonic('LSR',Size)
END
| 2:
IF (Left) THEN
WriteMnemonic('ROXL',Size)
ELSE
WriteMnemonic('ROXR',Size)
END
| 3:
IF Left THEN
WriteMnemonic('ROL',Size)
ELSE
WriteMnemonic('ROR',Size)
END
END (*CASE*);
IF (ASH(Inst,-5) MOD 2) = 1 THEN
Write1EA(0,Count,FALSE)
ELSE
TabTo(18);
IF Count = 0 THEN
WriteString('#8')
ELSE
Write('#');
WriteHex(Count,1)
END
END;
Write(',');
WriteEA(0,Reg,FALSE)
END (*IF*)
END LineE;
PROCEDURE Disassemble(data:ADDRESS;loadpoint,maxbyte:CARDINAL);
VAR
nibble,w:CARDINAL;
i :CARDINAL;
BEGIN
ReadCount := 0;
LoadOffset := loadpoint;
DataPointer := data;
WHILE (ReadCount < maxbyte) DO
WordCount := 0;
WriteHex(ReadCount + loadpoint,5);
WriteString(' ');
Read(w);
nibble := ASH(w,-12) MOD 16;
CASE nibble OF
0:
Line0(w)
| 1,2,3:
DecMove(w)
| 4:
Line4(w)
| 5:
Line5(w)
| 6:
Line6(w)
| 7:
Line7(w)
| 8:
Line8(w)
| 9:
Line9(w)
| 0AH:
WriteString('A-LINE');
TabTo(18);
WriteHex(w,4)
| 0BH:
LineB(w)
| 0CH:
LineC(w)
| 0DH:
LineD(w)
| 0EH:
LineE(w)
| 0FH:
WriteString('F-LINE');
TabTo(18);
WriteHex(w,4)
END (*CASE*);
TabTo(40);
Write(11C); (* write a tab *);
FOR i := 0 TO WordCount - 1 DO
WriteHex(WordsUsed[i],5)
END;
WriteLn
END (*WHILE*)
END Disassemble;
END Disasm.
!Funky!Stuff!