Syntax10.Scn.Fnt MODULE Decoder; (* Disassembler for MC68020-code with coprocessor MC68881. Diplomarbeit Samuel Urech Programming language: Oberon-2 on Ceres-1 Date: 7.11.92 Current version: 23.2.93 *) IMPORT Oberon, Texts, Files, TextFrames, MenuViewers; CONST DUMMY = 0; PC = -1; (* instructions *) ORI = 0; ANDI = 1; EORI = 2; CMPI = 3; ADDI = 4; SUBI = 5; JMP = 6; JSR = 7; PEA = 8; NBCD = 9; TAS = 10; RTD = 11; STOP = 12; MUL = 13; dIV = 14; ADD = 15; AND = 16; CMP = 17; EOR = 18; oR = 19; SUB = 20; ABCD = 21; SBCD = 22; PACK = 23; UNPK = 24; ADDA = 25; CMPA = 26; SUBA = 27; ADDX = 28; SUBX = 29; ASL = 30; ASR = 31; LSL = 32; LSR = 33; ROL = 34; ROR = 35; ROXL = 36; ROXR = 37; BFTST = 38; BFCHG = 39; BFEXTU = 40; BFEXTS = 41; BFCLR = 42; BFFFO = 43; BFSET = 44; (* coprocessor opcodes *) FABS = 18H; FACOS = 1CH; FADD = 22H; FASIN = 0CH; FATAN = 0AH; FATANH = 0DH; FCMP = 38H; FCOS = 1DH; FCOSH = 19H; FDIV = 20H; FETOX = 10H; FETOXM1 = 8; FGETEXP = 1EH; FGETMAN = 1FH; FINT = 1; FINTRZ = 3; FLOG10 = 15H; FLOG2 = 16H; FLOGN = 14H; FLOGNP1 = 6; FMOD = 21H; FMOVE = 0; FMUL = 23H; FNEG = 1AH; FREM = 25H; FSCALE = 26H; FSGLDIV = 24H; FSGLMUL = 27H; FSIN = 0EH; FSINH = 2; FSQRT = 4; FSUB = 28H; FTAN = 0FH; FTANH = 9; FTENTOX = 12H; FTST = 3AH; FTWOTOX = 11H; (* Floating Point Condition Codes *) FEQ = 1; FNE = 0EH; FGT = 12H; FNGT = 1DH; FGE = 13H; FNGE = 1CH; FLT = 14H; FNLT = 1BH; FLE = 15H; FNLE = 1AH; FGL = 16H; FNGL = 19H; FGLE = 17H; FNGLE = 18H; FOGT = 2; FULE = 0DH; FOGE = 3; FULT = 0CH; FOLT = 4; FUGE = 0BH; FOLE = 5; FUGT = 0AH; FOGL = 6; FUEQ = 9; fOR = 7; FUN = 8; FF = 0; FT = 0FH; FSF = 10H; FST = 1FH; FSEQ = 11H; FSNE = 1EH; (* instruction sizes *) byte = 0; word = 1; long = 2; other = 3; (* structure forms *) Byte = 1; Bool = 2; Char = 3; SInt = 4; Int = 5; LInt = 6; Real = 7; LReal = 8; Set = 9; String = 10; Pointer = 13; ProcTyp = 14; Comp = 15; BlockMisaligned = "Block misaligned."; VAR scanner : Texts.Scanner; writer : Texts.Writer; file : Files.File; rider : Files.Rider; frame : TextFrames.Frame; output : Texts.Text; viewer : MenuViewers.Viewer; pc : LONGINT; PROCEDURE Getbits( x : INTEGER; from, to : INTEGER) : INTEGER; (* Returns a number of bits of a number. *) BEGIN (* Getbits *) RETURN SHORT( ASH( x, -to ) MOD ASH( 2, from - to ) ) END Getbits; PROCEDURE Write( ch : CHAR ); (* Writes a character to the output. *) BEGIN Texts.Write( writer,ch ); END Write; PROCEDURE WriteString( s : ARRAY OF CHAR ); (* Writes a string to the output. *) BEGIN Texts.WriteString( writer, s ); END WriteString; PROCEDURE WriteLn; (* Writes a line feed to the output. *) BEGIN Texts.WriteLn( writer ); END WriteLn; PROCEDURE WriteInt( x : LONGINT ); (* Writes a longint to the output. *) BEGIN Texts.WriteInt( writer, x, 0 ); END WriteInt; PROCEDURE WriteHex( x : LONGINT ); (* Writes a longint in hexadecimal form to the output. *) BEGIN Texts.WriteHex( writer, x ); END WriteHex; PROCEDURE Read( VAR ch : CHAR ); (* Reads a character from the file. *) BEGIN (* Read *) Files.Read( rider, ch ); END Read; PROCEDURE ReadInt( VAR x : INTEGER ); (* Reads a word from the file. *) VAR hi, lo : CHAR; BEGIN (* ReadInt *) Files.Read( rider, hi ); Files.Read( rider, lo ); x := 100H * ORD( hi )+ ORD( lo ); INC( pc, 2 ); END ReadInt; PROCEDURE ReadLongint( VAR x : LONGINT ); (* Reads a longword from the file. *) VAR lo : LONGINT; hi, l : INTEGER; BEGIN (* ReadLongint *) ReadInt( hi ); ReadInt( l ); lo := l; IF lo < 0 THEN INC( lo, 65536 ); END; x := 10000H * hi + lo; END ReadLongint; PROCEDURE ReadDynint( VAR x : LONGINT ); (* Reads an integer of dynamic length. *) VAR n : LONGINT; shift : SHORTINT; ch : CHAR; BEGIN (* ReadDynint *) shift := 0; n := 0; Files.Read( rider, ch ); WHILE ORD( ch ) >= 128 DO INC( n, ASH( ORD( ch ) MOD 128, shift ) ); INC( shift, 7 ); Files.Read( rider, ch ); END; (* WHILE *) x := n + ASH( ORD( ch ) MOD 64, shift ) - ASH( ORD( ch ) DIV 64, shift ) * 64 END ReadDynint; PROCEDURE ReadString( VAR string : ARRAY OF CHAR; len : INTEGER ); (* Reads a string from the file. Reads at least len characters. *) VAR i : INTEGER; ch : CHAR; BEGIN (* ReadString *) i := 0; REPEAT Read( ch ); string[ i ] := ch; INC( i ); UNTIL ch = 0X; WHILE i < len DO string[ i ] := 0X; Read( ch ); INC( i ); END; END ReadString; PROCEDURE WriteType( ch : CHAR ); (* Writes the given type in plain text. *) BEGIN (* WriteType *) CASE ORD( ch ) OF Byte : WriteString( " : BYTE" ); | Bool : WriteString( " : BOOLEAN" ); | Char : WriteString( " : CHAR" ); | SInt : WriteString( " : SHORTINT" ); | Int : WriteString( " : INTEGER" ); | LInt : WriteString( " : LONGINT" ); | Real : WriteString( " : REAL" ); | LReal : WriteString( " : LONGREAL" ); | Set : WriteString( " : SET" ); | String : WriteString( " : String" ); | Pointer : WriteString( " : POINTER" ); | ProcTyp : WriteString( " : PROCEDURE" ); | Comp : WriteString( " : Composite" ); ELSE WriteString( " : Undefined" ); END; (* CASE *) WriteString( " " ); END WriteType; PROCEDURE WriteRegister( da, reg : INTEGER ); (* Writes a register. *) BEGIN (* WriteRegister *) IF da = 0 THEN Write( "D" ); ELSE Write( "A" ); END; (* IF *) WriteInt( reg ); END WriteRegister; PROCEDURE WriteCondition( condition : INTEGER ); (* Writes a condition. *) BEGIN (* WriteCondition *) CASE condition OF 0 : Write( "T" ); | 1 : Write( "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" ); | 10 : WriteString( "PL" ); | 11 : WriteString( "MI" ); | 12 : WriteString( "GE" ); | 13 : WriteString( "LT" ); | 14 : WriteString( "GT" ); | 15 : WriteString( "LE" ); END; (* CASE *) END WriteCondition; PROCEDURE WriteFloatCondition( condition : INTEGER ); (* Writes a coprocessor condition. *) BEGIN (* WriteFloatCondition *) CASE condition OF FEQ : WriteString( "EQ" ); | FNE : WriteString( "NE" ); | FGT : WriteString( "GT" ); | FNGT : WriteString( "NGT" ); | FGE : WriteString( "GE" ); | FNGE : WriteString( "NGE" ); | FLT : WriteString( "LT" ); | FNLT : WriteString( "NLT" ); | FLE : WriteString( "LE" ); | FNLE : WriteString( "NLE" ); | FGL : WriteString( "GL" ); | FNGL : WriteString( "NGL" ); | FGLE : WriteString( "GLE" ); | FNGLE : WriteString( "NGLE" ); | FOGT : WriteString( "OGT" ); | FULE : WriteString( "ULE" ); | FOGE : WriteString( "OGE" ); | FULT : WriteString( "ULT" ); | FOLT : WriteString( "OLT" ); | FUGE : WriteString( "UGE" ); | FOLE : WriteString( "OLE" ); | FUGT : WriteString( "UGT" ); | FOGL : WriteString( "OGL" ); | FUEQ : WriteString( "UEQ" ); | fOR : WriteString( "OR" ); | FUN : WriteString( "UN" ); | FF : Write( "F" ); | FT : Write( "T" ); | FSF : WriteString( "SF" ); | FST : WriteString( "ST" ); | FSEQ : WriteString( "SEQ" ); | FSNE : WriteString( "SNE" ); END; (* CASE *) END WriteFloatCondition; PROCEDURE WriteSize( size : INTEGER ); (* Writes an operand size. *) BEGIN CASE size OF byte : WriteString( ".B " ); | word : WriteString( ".W " ); | long : WriteString( ".L " ); | other : WriteString( "illegal operand size." ); END; (* CASE *) END WriteSize; PROCEDURE WriteFloatFormat( format : INTEGER; VAR size : INTEGER ); (* Writes an operand format of the coprocessor and returns the size of integer formats. *) BEGIN (* WriteFloatFormat *) size := other; CASE format OF 0 : WriteString( "L " ); size := long; | 1 : WriteString( "S " ); | 2 : WriteString( "X " ); | 3 : WriteString( "P " ); | 4 : WriteString( "W " ); size := word; | 5 : WriteString( "D " ); | 6 : WriteString( "B " ); size := byte; | 7 : WriteString( "P " ); END; (* CASE *) END WriteFloatFormat; PROCEDURE WriteComplexAddrMode( reg : INTEGER ); (* Reads extension word(s) if necessary and writes a complex adressing mode. If reg = PC, the addressing mode is PC-relative. *) VAR extension, bdSize, suppressBase, disp : INTEGER; PROCEDURE WriteBaseDisplacement( bdSize, suppressBase, reg : INTEGER ); (* Reads the base displacement and writes it, writes address register or "CB", if necessary. *) VAR displacement : INTEGER; longDisplacement, offset : LONGINT; BEGIN (* WriteBaseDisplacement *) IF reg = PC THEN offset := pc - 2; ELSE offset := 0; END; (* IF *) CASE bdSize OF 0 : WriteString( "illegal displacement size." ); | 1 : (* no displacement *) | 2 : ReadInt( displacement ); WriteInt( displacement + offset ); | 3 : ReadLongint( longDisplacement ); WriteInt( longDisplacement + offset ); END; (* CASE *) IF suppressBase = 0 THEN IF reg = PC THEN WriteString( ", PC" ); ELSE WriteString( ", A" ); WriteInt( reg ); END; (* IF *) END; (* IF *) END WriteBaseDisplacement; PROCEDURE WriteIndexRegister( extension : INTEGER ); (* Writes an index register with size and scaling. *) BEGIN (* WriteIndexRegister *) WriteRegister( Getbits( extension, 15, 15 ), Getbits( extension, 14, 12 ) ); IF Getbits( extension, 11, 11 ) = 0 THEN WriteString( ".W*" ); ELSE WriteString( ".L*" ); END; (* IF *) CASE Getbits( extension, 10, 9 ) OF 0 : Write( "1" ); | 1 : Write( "2" ); | 2 : Write( "4" ); | 3 : Write( "8" ); END; (* CASE *) END WriteIndexRegister; PROCEDURE WriteOuterDisplacement( long : BOOLEAN ); (* Writes the outer displacement, which can be one or two words. *) VAR displacement : INTEGER; longDisplacement : LONGINT; BEGIN (* WriteOuterDisplacement *) IF long THEN ReadLongint( longDisplacement ); WriteInt( longDisplacement ); ELSE ReadInt( displacement ); WriteInt( displacement ); END; (* IF *) END WriteOuterDisplacement; BEGIN (* WriteComplexAddrMode *) ReadInt( extension ); Write( "(" ); IF Getbits( extension, 8, 8 ) = 0 THEN disp := Getbits( extension, 7, 0 ); IF reg = PC THEN IF disp > 127 THEN WriteInt( pc - 2 + disp - 256 ); ELSE WriteInt( pc - 2 + disp ); END; (* IF *) WriteString( ", CB" ); ELSE IF disp > 127 THEN WriteInt( disp - 256 ); ELSE WriteInt( disp ); END; (* IF *) WriteString( ", A" ); WriteInt( reg ); END; (* IF *) WriteString( ", " ); WriteIndexRegister( extension ); ELSE bdSize := Getbits( extension, 5, 4 ); suppressBase := Getbits( extension, 7, 7 ); IF Getbits( extension, 6, 6 ) = 0 THEN CASE Getbits( extension, 2, 0 ) OF 0 : WriteBaseDisplacement( bdSize, suppressBase, reg ); WriteString( ", " ); WriteIndexRegister( extension ); | 1 : Write( "[" ); WriteBaseDisplacement( bdSize, suppressBase, reg ); WriteString( ", " ); WriteIndexRegister( extension ); Write( "]" ); | 2 : Write( "[" ); WriteBaseDisplacement( bdSize, suppressBase, reg ); WriteString( ", " ); WriteIndexRegister( extension ); WriteString( "], " ); WriteOuterDisplacement( FALSE ); | 3 : Write( "[" ); WriteBaseDisplacement( bdSize, suppressBase, reg ); WriteString( ", " ); WriteIndexRegister( extension ); WriteString( "], " ); WriteOuterDisplacement( TRUE ); | 4 : WriteString( "illegal addressing mode." ); | 5 : Write( "[" ); WriteBaseDisplacement( bdSize, suppressBase, reg ); Write( "]" ); WriteString( ", " ); WriteIndexRegister( extension ); | 6 : Write( "[" ); WriteBaseDisplacement( bdSize, suppressBase, reg ); WriteString( "], " ); WriteIndexRegister( extension ); WriteString( ", " ); WriteOuterDisplacement( FALSE ); | 7 : Write( "[" ); WriteBaseDisplacement( bdSize, suppressBase, reg ); WriteString( "], " ); WriteIndexRegister( extension ); WriteString( ", " ); WriteOuterDisplacement( TRUE ); END; (* CASE *) ELSE (* without index *) CASE Getbits( extension, 2, 0 ) OF 0 : WriteBaseDisplacement( bdSize, suppressBase, reg ); | 1 : Write( "[" ); WriteBaseDisplacement( bdSize, suppressBase, reg ); Write( "]" ); | 2 : Write( "[" ); WriteBaseDisplacement( bdSize, suppressBase, reg ); WriteString( "], " ); WriteOuterDisplacement( FALSE ); | 3 : Write( "[" ); WriteBaseDisplacement( bdSize, suppressBase, reg ); WriteString( "], " ); WriteOuterDisplacement( TRUE ); | 4, 5, 6, 7 : WriteString( "illegal addressing mode." ); END; (* CASE *) END; (* IF *) END; (* IF *) Write( ")" ); END WriteComplexAddrMode; PROCEDURE SingleAddressDecode( mode, reg, size : INTEGER ); (* Decodes an effective address comletely. Extension words are read if necessary. *) VAR displacement, address, data : INTEGER; longAddress, longData : LONGINT; BEGIN (* SingleAddressDecode *) CASE mode OF 0 : Write( "D" ); WriteInt( reg ); | 1 : Write( "A" ); WriteInt( reg ); | 2 : WriteString( "(A" ); WriteInt( reg ); Write( ")" ); | 3 : WriteString( "(A" ); WriteInt( reg ); WriteString( ")+" ); | 4 : WriteString( "-(A" ); WriteInt( reg ); Write( ")" ); | 5 : ReadInt( displacement ); Write( "(" ); WriteInt( displacement ); WriteString( ", A" ); WriteInt( reg ); Write( ")" ); | 6 : WriteComplexAddrMode( reg ); | 7 : CASE reg OF 0 : Write( "$" ); ReadInt( address ); WriteHex( address ); | 1 : Write( "$" ); ReadLongint( longAddress ); WriteHex( longAddress ); | 2 : ReadInt( displacement ); Write( "(" ); WriteInt( pc - 2 + displacement ); WriteString( ", CB)" ); | 3 : WriteComplexAddrMode( PC ); | 4 : Write( "#" ); CASE size OF byte, word : ReadInt( data ); WriteInt( data ); | long : ReadLongint( longData ); Write( "$" ); WriteHex( longData ); | other : WriteString( "illegal operand size." ); END; (* CASE *) | 5, 6, 7 : WriteString( "illegal addressing mode." ); END; (* CASE *) END; (* CASE *) END SingleAddressDecode; PROCEDURE Format1( op, mode, reg, size : INTEGER ); (* ORI, ANDI, EORI, ADDI, SUBI, CMPI *) VAR immData : INTEGER; longImmData : LONGINT; BEGIN (* Format1 *) CASE op OF ORI : WriteString( "ORI" ); | ANDI : WriteString( "ANDI" ); | EORI : WriteString( "EORI" ); | SUBI : WriteString( "SUBI" ); | ADDI : WriteString( "ADDI" ); | CMPI : WriteString( "CMPI" ); ELSE WriteString( "Illegal instruction." ); END; (* CASE *) CASE size OF 0 : WriteString( ".B #$" ); ReadInt( immData ); WriteHex( immData ); WriteString( ", " ); IF ( mode = 7 ) & ( reg = 4 ) THEN WriteString( "CCR" ); ELSE SingleAddressDecode( mode, reg, byte ); END; (* IF *) | 1 : WriteString( ".W #$" ); ReadInt( immData ); WriteHex( immData ); WriteString( ", " ); IF ( mode = 7 ) & ( reg = 4 ) THEN WriteString( "SR" ); ELSE SingleAddressDecode( mode, reg, word ); END; (* IF *) | 2 : WriteString( ".L #$" ); ReadLongint( longImmData ); WriteHex( longImmData ); WriteString( ", " ); SingleAddressDecode( mode, reg, long ); | 3 : WriteString( "illegal operand size." ); END; (* CASE *) END Format1; PROCEDURE Format2( mode, reg : INTEGER ); (* BFINS *) VAR instr2 : INTEGER; BEGIN (* Format2 *) WriteString( "BFINS " ); ReadInt( instr2 ); Write( "D" ); WriteInt( Getbits( instr2, 14, 12 ) ); WriteString( ", " ); SingleAddressDecode( mode, reg, DUMMY ); WriteString( " {" ); IF Getbits( instr2, 11, 11 ) = 0 THEN WriteInt( Getbits( instr2, 10, 6 ) ); ELSE Write( "D" ); WriteInt( Getbits( instr2, 8, 6 ) ); END; (* IF *) Write( ":" ); IF Getbits( instr2, 5, 5 ) = 0 THEN WriteInt( Getbits( instr2, 4, 0 ) ); ELSE Write( "D" ); WriteInt( Getbits( instr2, 2, 0 ) ); END; (* IF *) Write( "}" ); END Format2; PROCEDURE Format3( mode, reg, size : INTEGER ); (* CHK2, CMP2 *) VAR instr2 : INTEGER; BEGIN (* Format3 *) ReadInt( instr2 ); IF Getbits( instr2, 10, 0 ) = 0 THEN IF Getbits( instr2, 11, 11 ) = 0 THEN WriteString( "CMP2" ); ELSE WriteString( "CHK2" ); END; (* IF *) WriteSize( size ); SingleAddressDecode( mode, reg, byte ); WriteString( ", " ); WriteRegister( Getbits( instr2, 15, 15 ), Getbits( instr2, 14, 12 ) ); ELSE WriteString( "illegal instruction." ); END; (* IF *) END Format3; PROCEDURE Format4( op, mode, reg : INTEGER ); (* BCHG, BCLR, BSET, BTST, static bit number. *) VAR bitNr : INTEGER; BEGIN (* Format4 *) CASE op OF 0 : WriteString( "BTST #" ); | 1 : WriteString( "BCHG #" ); | 2 : WriteString( "BCLR #" ); | 3 : WriteString( "BSET #" ); END; (* CASE *) ReadInt( bitNr ); WriteInt( bitNr ); WriteString( ", " ); SingleAddressDecode( mode, reg, DUMMY ); END Format4; PROCEDURE Format5( mode, reg, size : INTEGER ); (* CAS, CAS2 *) VAR instr2, instr3 : INTEGER; BEGIN (* Format5 *) ReadInt( instr2 ); IF ( mode = 7 ) & ( reg = 4 ) THEN (* CAS2 *) ReadInt( instr3 ); WriteString( "CAS2" ); CASE size OF 0, 1 : WriteString( "illegal operand size." ); | 2 : WriteString( ".W D" ); | 3 : WriteString( ".L D" ); END; (* CASE *) WriteInt( Getbits( instr2, 2, 0 ) ); WriteString( ":D" ); WriteInt( Getbits( instr3, 2, 0 ) ); WriteString( ", D" ); WriteInt( Getbits( instr2, 8, 6 ) ); WriteString( ":D" ); WriteInt( Getbits( instr3, 8, 6 ) ); WriteString( ", (" ); WriteRegister( Getbits( instr2, 15, 15 ), Getbits( instr2, 14, 12 ) ); WriteString( "):(" ); WriteRegister( Getbits( instr3, 15, 15 ), Getbits( instr3, 14, 12 ) ); Write( ")" ); ELSE (* CAS *) WriteString( "CAS" ); CASE size OF 0 : WriteString( "illegal operand size." ); | 1 : WriteString( ".B D" ); | 2 : WriteString( ".W D" ); | 3 : WriteString( ".L D" ); END; (* CASE *) WriteInt( Getbits( instr2, 2, 0 ) ); WriteString( ", D" ); WriteInt( Getbits( instr2, 8, 6 ) ); WriteString( ", " ); SingleAddressDecode( mode, reg, DUMMY ); END; (* IF *) END Format5; PROCEDURE Format6( mode, reg, size : INTEGER ); (* MOVES *) VAR instr2 : INTEGER; BEGIN (* Format6 *) ReadInt( instr2 ); WriteString( "MOVES" ); WriteSize( size ); IF Getbits( instr2, 11, 11 ) = 0 THEN SingleAddressDecode( mode, reg, DUMMY ); WriteString( ", " ); WriteRegister( Getbits( instr2, 15, 15 ), Getbits( instr2, 14, 12 ) ); ELSE WriteRegister( Getbits( instr2, 15, 15 ), Getbits( instr2, 14, 12 ) ); WriteString( ", " ); SingleAddressDecode( mode, reg, DUMMY ); END; (* IF *) END Format6; PROCEDURE Format7( da, reg : INTEGER ); (* RTM *) BEGIN (* Format7 *) WriteString( "RTM " ); WriteRegister( da, reg ); END Format7; PROCEDURE Format8( mode, reg : INTEGER ); (* CALLM *) VAR instr2 : INTEGER; BEGIN (* Format8 *) WriteString( "CALLM #" ); ReadInt( instr2 ); WriteInt( instr2 ); WriteString( ", " ); SingleAddressDecode( mode, reg, DUMMY ); END Format8; PROCEDURE Format9( dataReg, direction, size, addrReg : INTEGER ); (* MOVEP *) VAR displacement : INTEGER; BEGIN (* Format9 *) WriteString( "MOVEP" ); IF size = 0 THEN WriteString( ".W " ); ELSE WriteString( ".L " ); END; ReadInt( displacement ); IF direction = 0 THEN Write( "(" ); WriteInt( displacement ); WriteString( ", A" ); WriteInt( addrReg ); WriteString( "), D" ); WriteInt( dataReg ); ELSE Write( "D" ); WriteInt( dataReg ); WriteString( ", (" ); WriteInt( displacement ); WriteString( ", A" ); WriteInt( addrReg ); Write( ")" ); END; (* IF *) END Format9; PROCEDURE Format10( op, dataReg, mode, reg : INTEGER ); (* BCHG, BCLR, BSET, BTST, dynamic bit number. *) BEGIN (* Format10 *) CASE op OF 0 : WriteString( "BTST D" ); | 1 : WriteString( "BCHG D" ); | 2 : WriteString( "BCLR D" ); | 3 : WriteString( "BSET D" ); END; (* CASE *) WriteInt( dataReg ); WriteString( ", " ); SingleAddressDecode( mode, reg, DUMMY ); END Format10; PROCEDURE Format11( size, sourceMode, sourceReg, destMode, destReg : INTEGER ); (* MOVE, MOVEA *) BEGIN (* Format11 *) WriteString( "MOVE" ); IF destMode = 1 THEN Write( "A" ); END; (* IF *) CASE size OF 0 : WriteString( "illegal operand size." ); | 1 : WriteString( ".B " ); SingleAddressDecode( sourceMode, sourceReg, byte ); | 2 : WriteString( ".L " ); SingleAddressDecode( sourceMode, sourceReg, long ); | 3 : WriteString( ".W " ); SingleAddressDecode( sourceMode, sourceReg, word ); END; (* CASE *) WriteString( ", " ); SingleAddressDecode( destMode, destReg, DUMMY ); END Format11; PROCEDURE Format12( op, size, mode, reg : INTEGER ); (* CLR, NEG, NEGX, NOT, TST *) BEGIN (* Format12 *) CASE op OF 0 : WriteString( "NEGX" ); | 1 : WriteString( "CLR" ); | 2 : WriteString( "NEG" ); | 3 : WriteString( "NOT" ); | 5 : WriteString( "TST" ); ELSE WriteString( "illegal instruction." ); END; (* CASE *) WriteSize( size ); SingleAddressDecode( mode, reg, DUMMY ); END Format12; PROCEDURE Format13( size, reg : INTEGER ); (* LINK *) VAR disp : INTEGER; longDisp : LONGINT; BEGIN (* Format13 *) WriteString( "LINK" ); IF size = 0 THEN WriteString( ".W A" ); WriteInt( reg ); WriteString( ", #" ); ReadInt( disp ); WriteInt( disp ); ELSE WriteString( ".L A" ); WriteInt( reg ); WriteString( ", #" ); ReadLongint( longDisp ); WriteInt( longDisp ); END; (* IF *) END Format13; PROCEDURE Format14( op, mode, reg : INTEGER ); (* JMP, JSR, PEA, NBCD, TAS, ASL, ASR, LSL, LSR, ROL, ROR, ROXL, ROXR *) BEGIN (* Format14 *) CASE op OF JMP : WriteString( "JMP " ); | JSR : WriteString( "JSR " ); | PEA : WriteString( "PEA.L " ); | NBCD : WriteString( "NBCD.B " ); | TAS : WriteString( "TAS.B " ); | ASL : WriteString( "ASL.W " ); | ASR : WriteString( "ASR.W " ); | LSL : WriteString( "LSL.W " ); | LSR : WriteString( "LSR.W " ); | ROL : WriteString( "ROL.W " ); | ROR : WriteString( "ROR.W " ); | ROXL : WriteString( "ROXL.W " ); | ROXR : WriteString( "ROXR.W " ); END; (* CASE *) SingleAddressDecode( mode, reg, DUMMY ); END Format14; PROCEDURE Format15( op, data : INTEGER ); (* SWAP, BKPT, TRAP, UNLK, MOVE from USP, RTD, EXT.W, EXT.L, EXTB.L *) BEGIN (* Format15 *) CASE op OF 0 : WriteString( "SWAP.W D" ); | 1 : WriteString( "BKPT #" ); | 2 : WriteString( "TRAP #" ); | 3 : WriteString( "UNLK A" ); | 4 : WriteString( "MOVE.L USP, A" ); | 5 : WriteString( "EXT.W D" ); | 6 : WriteString( "EXT.L D" ); | 7 : WriteString( "EXTB.L D" ); END; (* CASE *) WriteInt( data ); END Format15; PROCEDURE Format16( reg : INTEGER ); (* MOVE to USP *) BEGIN (* Format16 *) WriteString( "MOVE.L A" ); WriteInt( reg ); WriteString( ", USP" ); END Format16; PROCEDURE Format17( direction : INTEGER ); (* MOVEC *) VAR instr2 : INTEGER; BEGIN (* Format17 *) ReadInt( instr2 ); IF direction = 0 THEN WriteString( "MOVEC.L Control Register #" ); WriteInt( Getbits( instr2, 11, 0 ) ); WriteString( ", " ); WriteRegister( Getbits( instr2, 15, 15 ), Getbits( instr2, 14, 12 ) ); ELSE WriteString( "MOVEC.L " ); WriteRegister( Getbits( instr2, 15, 15 ), Getbits( instr2, 14, 12 ) ); WriteString( ", Control Register #" ); WriteInt( Getbits( instr2, 11, 0 ) ); END; (* IF *) END Format17; PROCEDURE Format18( op : INTEGER ); (* RTD, STOP *) VAR data : INTEGER; BEGIN (* Format18 *) CASE op OF RTD : WriteString( "RTD #" ); | STOP : WriteString( "STOP #" ); END; (* CASE *) ReadInt( data ); WriteInt( data ); END Format18; PROCEDURE Format19( direction, size, mode, reg : INTEGER ); (* MOVEM *) VAR regList : INTEGER; BEGIN (* Format19 *) IF size = 0 THEN WriteString( "MOVEM.W " ); ELSE WriteString( "MOVEM.L " ); END; (* IF *) ReadInt( regList ); IF direction = 0 THEN WriteString( "#$" ); WriteHex( regList ); WriteString( ", " ); SingleAddressDecode( mode, reg, DUMMY ); ELSE SingleAddressDecode( mode, reg, DUMMY ); WriteString( ", #$" ); WriteHex( regList ); END; (* IF *) END Format19; PROCEDURE Format20( op, mode, reg : INTEGER ); (* MOVE CCR, MOVE SR *) BEGIN (* Format20 *) CASE op OF 0 : (* MOVE from SR *) WriteString( "MOVE.W SR, " ); SingleAddressDecode( mode, reg, DUMMY ); | 1 : (* MOVE from CCR *) WriteString( "MOVE.W CCR, " ); SingleAddressDecode( mode, reg, DUMMY ); | 2 : (* MOVE to CCR *) WriteString( "MOVE.W " ); SingleAddressDecode( mode, reg, word ); WriteString( ", SR" ); | 3 : (* MOVE to SR *) WriteString( "MOVE.W " ); SingleAddressDecode( mode, reg, word ); WriteString( ", CCR" ); END; (* CASE *) END Format20; PROCEDURE Format21( size, dataReg, mode, reg : INTEGER ); (* CHK *) BEGIN (* Format21 *) WriteString( "CHK" ); IF size = 1 THEN WriteString( ".W " ); ELSE WriteString( ".L " ); END; (* IF *) SingleAddressDecode( mode, reg, size ); WriteString( ", D" ); WriteInt( dataReg ); END Format21; PROCEDURE Format22( addrReg, mode, reg : INTEGER ); (* LEA *) BEGIN (* Format22 *) WriteString( "LEA " ); SingleAddressDecode( mode, reg, DUMMY ); WriteString( ", A" ); WriteInt( addrReg ); END Format22; PROCEDURE Format23( condition, reg : INTEGER ); (* DBcc *) VAR disp : INTEGER; BEGIN (* Format23 *) WriteString( "DB" ); WriteCondition( condition ); WriteString( " D" ); WriteInt( reg ); WriteString( ", " ); ReadInt( disp ); WriteInt( pc - 2 + disp ); END Format23; PROCEDURE Format24( condition, mode, reg : INTEGER ); (* Scc *) BEGIN (* Format24 *) Write( "S" ); WriteCondition( condition ); WriteString( ".B " ); SingleAddressDecode( mode, reg, DUMMY ); END Format24; PROCEDURE Format25( condition, opmode : INTEGER ); (* TRAPcc *) VAR data : INTEGER; longData : LONGINT; BEGIN (* Format25 *) WriteString( "TRAP" ); WriteCondition( condition ); CASE opmode OF 2 : WriteString( ".W #" ); ReadInt( data ); WriteInt( data ); | 3 : WriteString( ".L #" ); ReadLongint( longData ); WriteInt( longData ); | 4 : END; (* CASE *) END Format25; PROCEDURE Format26( op, data, size, mode, reg : INTEGER ); (* ADDQ, SUBQ *) BEGIN (* Format26 *) IF op = 0 THEN WriteString( "ADDQ" ); ELSE WriteString( "SUBQ" ); END; (* IF *) WriteSize( size ); Write( "#" ); IF data = 0 THEN WriteInt( 8 ); ELSE WriteInt( data ); END; (* IF *) WriteString( ", " ); SingleAddressDecode( mode, reg, DUMMY ); END Format26; PROCEDURE Format27( condition, displacement : INTEGER ); (* Bcc, BRA, BSR *) VAR wordDisplacement : INTEGER; longDisplacement : LONGINT; BEGIN (* Format27 *) CASE condition OF 0 : WriteString( "BRA" ); | 1 : WriteString( "BSR" ); ELSE Write( "B" ); WriteCondition( condition ); END; CASE displacement OF 0 : WriteString( ".W " ); ReadInt( wordDisplacement ); WriteInt( pc - 2 + wordDisplacement ); | 255 : WriteString( ".L " ); ReadLongint( longDisplacement ); WriteInt( pc - 2 + longDisplacement ); ELSE WriteString( ".B " ); IF displacement > 127 THEN WriteInt( pc - 2 + displacement - 256 ); ELSE WriteInt( pc - 2 + displacement ); END; (* IF *) END; (* CASE *) END Format27; PROCEDURE Format28( reg, data : INTEGER ); (* MOVEQ *) BEGIN (* Format28 *) WriteString( "MOVEQ.L #" ); IF data > 127 THEN WriteInt( data-256 ); ELSE WriteInt( data ); END; (* IF *) WriteString( ", D" ); WriteInt( reg ); END Format28; PROCEDURE Format29( op, mode, reg : INTEGER ); (* MULS, MULU, DIVS, DIVSL, DIVU, DIVUL, long form *) VAR instr2, size, qReg, rReg : INTEGER; BEGIN (* Format29 *) ReadInt( instr2 ); size := Getbits( instr2, 10, 10 ); qReg := Getbits( instr2, 14, 12 ); rReg := Getbits( instr2, 2, 0 ); IF op = MUL THEN WriteString( "MUL" ); ELSE WriteString( "DIV" ); END; (* IF *) IF Getbits( instr2, 11, 11 ) = 0 THEN Write( "U" ); ELSE Write( "S" ); END; (* IF *) IF ( op = dIV ) & ( size = 0 ) & ( rReg # qReg ) THEN Write( "L" ); END; (* IF *) WriteString( ".L " ); SingleAddressDecode( mode, reg, long ); WriteString( ", " ); IF qReg # rReg THEN Write( "D" ); WriteInt( rReg ); Write( ":" ); END; (* IF *) Write( "D" ); WriteInt( qReg ); END Format29; PROCEDURE Format30( op, signed, dataReg, mode, reg : INTEGER ); (* MULS, MULU, DIVS, DIVU, short form *) BEGIN (* Format30 *) IF op = MUL THEN IF signed = 0 THEN WriteString( "MULU.W " ); ELSE WriteString( "MULS.W " ); END; ELSE IF signed = 0 THEN WriteString( "DIVU.W " ); ELSE WriteString( "DIVS.W " ); END; END; SingleAddressDecode( mode, reg, word ); WriteString( ", D" ); WriteInt( dataReg ); END Format30; PROCEDURE Format31( op, direction, dataReg, size, mode, reg : INTEGER ); (* ADD, AND, CMP, EOR, OR, SUB *) BEGIN (* Format31 *) CASE op OF ADD : WriteString( "ADD" ); | AND : WriteString( "AND" ); | CMP : WriteString( "CMP" ); | EOR : WriteString( "EOR" ); | oR : WriteString( "OR" ); | SUB : WriteString( "SUB" ); END; (* CASE *) WriteSize( size ); IF direction = 0 THEN SingleAddressDecode( mode, reg, size ); WriteString( ", D" ); WriteInt( dataReg ); ELSE Write( "D" ); WriteInt( dataReg ); WriteString( ", " ); SingleAddressDecode( mode, reg, size ); END; (* IF *) END Format31; PROCEDURE Format32( op, size, rm, xReg, yReg : INTEGER ); (* ABCD, SBCD, ADDX, SUBX *) BEGIN (* Format32 *) CASE op OF ABCD : WriteString( "ABCD" ); | SBCD : WriteString( "SBCD" ); | ADDX : WriteString( "ADDX" ); | SUBX : WriteString( "SUBX" ); END; (* CASE *) WriteSize( size ); IF rm = 0 THEN Write( "D" ); WriteInt( xReg ); WriteString( ", D" ); WriteInt( yReg ); ELSE WriteString( "-(A" ); WriteInt( xReg ); WriteString( "), -(A" ); WriteInt( yReg ); Write( ")" ); END; (* IF *) END Format32; PROCEDURE Format33( op, rm, xReg, yReg : INTEGER ); (* PACK, UNPK *) VAR adjustment : INTEGER; BEGIN (* Format33 *) IF op = PACK THEN WriteString( "PACK " ); ELSE WriteString( "UNPK " ); END; (* IF *) IF rm = 0 THEN Write( "D" ); WriteInt( xReg ); WriteString( ", D" ); WriteInt( yReg ); ELSE WriteString( "-(A" ); WriteInt( xReg ); WriteString( "), -(A" ); WriteInt( yReg ); Write( ")" ); END; (* IF *) WriteString( ", #" ); ReadInt( adjustment ); WriteInt( adjustment ); END Format33; PROCEDURE Format34( op, size, addrReg, mode, reg : INTEGER ); (* ADDA, CMPA, SUBA *) BEGIN (* Format34 *) CASE op OF ADDA : WriteString( "ADDA" ); | CMPA : WriteString( "CMPA" ); | SUBA : WriteString( "SUBA" ); END; (* CASE *) IF size = 0 THEN WriteString( ".W " ); ELSE WriteString( ".L " ); END; (* IF *) SingleAddressDecode( mode, reg, size+1 ); WriteString( ", A" ); WriteInt( addrReg ); END Format34; PROCEDURE Format35( size, xReg, yReg : INTEGER ); (* CMPM *) BEGIN (* Format35 *) WriteString( "CMPM" ); WriteSize( size ); WriteString( "(A" ); WriteInt( yReg ); WriteString( ")+, (A" ); WriteInt( xReg ); WriteString( ")+" ); END Format35; PROCEDURE Format36( opmode, xReg, yReg : INTEGER ); (* EXG *) BEGIN (* Format36 *) WriteString( "EXG.L " ); CASE opmode OF 16 : Write( "D" ); WriteInt( xReg ); WriteString( ", D" ); WriteInt( yReg ); | 17 : Write( "A" ); WriteInt( xReg ); WriteString( ", A" ); WriteInt( yReg ); | 33 : Write( "D" ); WriteInt( xReg ); WriteString( ", A" ); WriteInt( yReg ); ELSE WriteString( "illegal instruction." ); END; (* CASE *) END Format36; PROCEDURE Format37( op, mode, reg : INTEGER ); (* BFCHG, BFCLR, BFSET, BTST *) VAR instr2 : INTEGER; BEGIN (* Format37 *) CASE op OF BFCHG : WriteString( "BFCHG " ); | BFCLR : WriteString( "BFCLR " ); | BFSET : WriteString( "BFSET " ); | BFTST : WriteString( "BFTST " ); END; (* CASE *) ReadInt( instr2 ); SingleAddressDecode( mode, reg, DUMMY ); WriteString( " {" ); IF Getbits( instr2, 11, 11 ) = 0 THEN WriteInt( Getbits( instr2, 10, 6 ) ); ELSE Write( "D" ); WriteInt( Getbits( instr2, 8, 6 ) ); END; (* IF *) Write( ":" ); IF Getbits( instr2, 5, 5 ) = 0 THEN WriteInt( Getbits( instr2, 4, 0 ) ); ELSE Write( "D" ); WriteInt( Getbits( instr2, 2, 0 ) ); END; (* IF *) Write( "}" ); END Format37; PROCEDURE Format38( op, mode, reg : INTEGER ); (* BFEXTS, BFEXTU, BFFFO *) VAR instr2 : INTEGER; BEGIN (* Format38 *) CASE op OF BFEXTS : WriteString( "BFEXTS " ); | BFEXTU : WriteString( "BFEXTU " ); | BFFFO : WriteString( "BFFFO " ); END; (* CASE *) ReadInt( instr2 ); SingleAddressDecode( mode, reg, DUMMY ); WriteString( " {" ); IF Getbits( instr2, 11, 11 ) = 0 THEN WriteInt( Getbits( instr2, 10, 6 ) ); ELSE Write( "D" ); WriteInt( Getbits( instr2, 8, 6 ) ); END; (* IF *) Write( ":" ); IF Getbits( instr2, 5, 5 ) = 0 THEN WriteInt( Getbits( instr2, 4, 0 ) ); ELSE Write( "D" ); WriteInt( Getbits( instr2, 2, 0 ) ); END; (* IF *) WriteString( "}, D" ); WriteInt( Getbits( instr2, 14, 12 ) ); END Format38; PROCEDURE Format39( op, cntReg, direction, size, ir, reg : INTEGER ); (* ASL, ASR, LSL, ROXL, ROXR, ROL, ROR *) BEGIN (* Format39 *) CASE op OF 0 : WriteString( "AS" ); | 1 : WriteString( "LS" ); | 2 : WriteString( "ROX" ); | 3 : WriteString( "RO" ); END; (* CASE *) IF direction = 0 THEN Write( "R" ); ELSE Write( "L" ); END; (* IF *) WriteSize( size ); IF ir = 0 THEN Write( "#" ); IF cntReg = 0 THEN Write( "8" ); ELSE WriteInt( cntReg ); END; (* IF *) ELSE Write( "D" ); WriteInt( cntReg ); END; (* IF *) WriteString( ", D" ); WriteInt( reg ); END Format39; PROCEDURE Format40( destReg, romoffs : INTEGER ); (* FMOVECR *) BEGIN (* Format40 *) WriteString( "FMOVECR.X $" ); WriteHex( romoffs ); WriteString( ", FP" ); WriteInt( destReg ); END Format40; PROCEDURE Format41( opcode, mode, reg, rm, sourceSpec, destReg : INTEGER ); (* normal coprocessor operation *) VAR size : INTEGER; BEGIN (* Format41 *) CASE opcode OF FABS : WriteString( "FABS." ); | FACOS : WriteString( "FACOS." ); | FADD : WriteString( "FADD." ); | FASIN : WriteString( "FASIN." ); | FATAN : WriteString( "FATAN." ); | FATANH : WriteString( "FATANH." ); | FCMP : WriteString( "FCMP." ); | FCOS : WriteString( "FCOS." ); | FCOSH : WriteString( "FCOSH." ); | FDIV : WriteString( "FDIV." ); | FETOX : WriteString( "FETOX." ); | FETOXM1 : WriteString( "FETOXM1." ); | FGETEXP : WriteString( "FGETEXP." ); | FGETMAN : WriteString( "FGETMAN." ); | FINT : WriteString( "FINT." ); | FINTRZ : WriteString( "FINTRZ." ); | FLOG10 : WriteString( "FLOG10." ); | FLOG2 : WriteString( "FLOG2." ); | FLOGN : WriteString( "FLOGN." ); | FLOGNP1 : WriteString( "FLOGNP1." ); | FMOD : WriteString( "FMOD." ); | FMOVE : WriteString( "FMOVE." ); | FMUL : WriteString( "FMUL." ); | FNEG : WriteString( "FNEG." ); | FREM : WriteString( "FREM." ); | FSCALE : WriteString( "FSCALE." ); | FSGLDIV : WriteString( "FSGLDIV." ); | FSGLMUL : WriteString( "FSGLMUL." ); | FSIN : WriteString( "FSIN." ); | FSINH : WriteString( "FSINH." ); | FSQRT : WriteString( "FSQRT." ); | FSUB : WriteString( "FSUB." ); | FTAN : WriteString( "FTAN." ); | FTANH : WriteString( "FTANH." ); | FTENTOX : WriteString( "FTENTOX." ); | FTST : WriteString( "FTST." ); | FTWOTOX : WriteString( "FTWOTOX." ); ELSE WriteString( "illegal coprocessor instruction." ); END; (* CASE *) IF rm = 0 THEN WriteString( "X FP" ); WriteInt( sourceSpec ); ELSE WriteFloatFormat( sourceSpec, size ); SingleAddressDecode( mode, reg, size ); END; (* IF *) WriteString( ", FP" ); WriteInt( destReg ); END Format41; PROCEDURE Format42( mode, reg, rm, sourceSpec, destRegSin, destRegCos : INTEGER ); (* FSINCOS *) VAR size : INTEGER; BEGIN (* Format42 *) WriteString( "FSINCOS." ); IF rm = 0 THEN WriteString( "X FP" ); WriteInt( sourceSpec ); ELSE WriteFloatFormat( sourceSpec, size ); SingleAddressDecode( mode, reg, size ); END; (* IF *) WriteString( ", FP" ); WriteInt( destRegCos ); WriteString( ":FP" ); WriteInt( destRegSin ); END Format42; PROCEDURE Format43( mode, reg, dr, regList : INTEGER ); (* FMOVE(M) FPcr *) PROCEDURE WriteControlRegs( fpcr, fpsr, fpiar : INTEGER ); (* Writes a list of floating point control registers. *) VAR comma : BOOLEAN; BEGIN (* WriteControlRegs *) comma := FALSE; IF fpcr = 1 THEN WriteString( "FPCR" ); comma := TRUE; END; IF fpsr = 1 THEN IF comma THEN WriteString( ", " ); END; WriteString( "FPSR" ); comma := TRUE; END; IF fpiar = 1 THEN IF comma THEN WriteString( ", " ); END; WriteString( "FPIAR" ); END; END WriteControlRegs; BEGIN (* Format43 *) WriteString( "FMOVEM.L " ); IF dr = 0 THEN SingleAddressDecode( mode, reg, long ); WriteString( ", " ); WriteControlRegs( Getbits( regList, 2, 2 ), Getbits( regList, 1, 1 ), Getbits( regList, 0, 0 ) ); ELSE WriteControlRegs( Getbits( regList, 2, 2 ), Getbits( regList, 1, 1 ), Getbits( regList, 0, 0 ) ); WriteString( ", " ); SingleAddressDecode( mode, reg, long ); END; (* IF *) END Format43; PROCEDURE Format44( mode, reg, dr, statdyn, regList : INTEGER ); (* FMOVEM FPn *) BEGIN (* Format44 *) WriteString( "FMOVEM.X " ); IF dr = 0 THEN SingleAddressDecode( mode, reg, byte ); IF statdyn = 0 THEN (* static *) WriteString( ", #" ); WriteHex( regList ); ELSE (* dynamic *) WriteString( ", D" ); WriteInt( Getbits( regList, 6, 4 ) ); END; (* IF *) ELSE IF statdyn = 0 THEN (* static *) Write( "#" ); WriteHex( regList ); ELSE (* dynamic *) Write( "D" ); WriteInt( Getbits( regList, 6, 4 ) ); END; (* IF *) WriteString( ", " ); SingleAddressDecode( mode, reg, DUMMY ); END; (* IF *) END Format44; PROCEDURE Format45( mode, reg, sourceReg, destFormat, kfactor : INTEGER ); (* FMOVE from FPn *) VAR size : INTEGER; BEGIN (* Format45 *) WriteString( "FMOVE." ); WriteFloatFormat( destFormat, size ); WriteString( "FP" ); WriteInt( sourceReg ); WriteString( ", " ); SingleAddressDecode( mode, reg, size ); IF destFormat = 3 THEN (* static k-factor *) WriteString( "{#" ); WriteInt( kfactor ); Write( "}" ); ELSIF destFormat = 7 THEN (* dynamic k-factor *) WriteString( "{D" ); WriteInt( Getbits( kfactor, 6, 4 ) ); Write( "}" ); END; END Format45; PROCEDURE Format46( reg, condition : INTEGER ); (* FDBcc *) VAR disp : INTEGER; BEGIN (* Format46 *) WriteString( "FDB" ); WriteFloatCondition( condition ); WriteString( " D" ); WriteInt( reg ); WriteString( ", " ); ReadInt( disp ); WriteInt( pc - 2 + disp ); END Format46; PROCEDURE Format47( mode, reg, condition : INTEGER ); (* FScc *) BEGIN (* Format47 *) WriteString( "FS" ); WriteFloatCondition( condition ); WriteString( ".B " ); SingleAddressDecode( mode, reg, byte ); END Format47; PROCEDURE Format48( mode, condition : INTEGER ); (* FTRAPcc *) VAR data : INTEGER; longdata : LONGINT; BEGIN (* Format48 *) WriteString( "FTRAP" ); WriteFloatCondition( condition ); CASE mode OF 2 : ReadInt( data ); WriteString( ".W #" ); WriteInt( data ); | 3 : ReadLongint( longdata ); WriteString( ".L #" ); WriteInt( longdata ); | 4 : (* nothing *) ELSE WriteString( "illegal operand mode." ); END; (* CASE *) END Format48; PROCEDURE Format49( size, condition : INTEGER ); (* FBcc *) VAR disp : INTEGER; longdisp : LONGINT; BEGIN (* Format49 *) WriteString( "FB" ); WriteFloatCondition( condition ); IF size = 0 THEN WriteString( ".W " ); ReadInt( disp ); WriteInt( pc - 2 + disp ); ELSE WriteString( ".L " ); ReadLongint( longdisp ); WriteInt( pc - 2 + longdisp ); END; (* IF *) END Format49; PROCEDURE Format50( opcode, mode, reg : INTEGER ); (* FSAVE, FRESTORE *) BEGIN (* Format50 *) CASE opcode OF 4 : WriteString( "FSAVE " ); | 5 : WriteString( "FRESTORE " ); ELSE WriteString( "illegal coprocessor instruction." ); END; (* CASE *) SingleAddressDecode( mode, reg, long ); END Format50; PROCEDURE Format51( nr : INTEGER ); (* TRAP *) BEGIN (* Format51 *) WriteString( "TRAP #" ); WriteInt( nr ); END Format51; PROCEDURE CoprocessorDecode( instruction, mode, reg : INTEGER ); (* Decodes a coprocessor instruction. *) VAR cpinstruction : INTEGER; BEGIN (* CoprocessorDecode *) IF Getbits( instruction, 11, 9 ) # 1 THEN WriteString( "wrong coprocessor." ); ELSE CASE Getbits( instruction, 8, 6 ) OF 0 : ReadInt( cpinstruction ); IF ( Getbits( cpinstruction, 15, 15 ) = 0 ) & ( Getbits( cpinstruction, 13, 13 ) = 0 ) THEN IF Getbits( cpinstruction, 12, 10 ) = 7 THEN (* FMOVECR *) IF Getbits( instruction, 5, 0 ) = 0 THEN (* FMOVECR *) Format40( Getbits( cpinstruction, 9, 7 ), Getbits( cpinstruction, 6, 0 ) ); ELSE WriteString( "illegal coprocessor instruction." ); END; (* IF *) ELSE (* normal coprocessor operation *) IF Getbits( cpinstruction, 6, 3 ) = 6 THEN (* FSINCOS *) Format42( mode, reg, Getbits( cpinstruction, 14, 14 ), Getbits( cpinstruction, 12, 10 ), Getbits( cpinstruction, 9, 7 ), Getbits( cpinstruction, 2, 0 ) ); ELSE (* normal coprocessor operation *) Format41( Getbits( cpinstruction, 6, 0 ), mode, reg, Getbits( cpinstruction, 14, 14 ), Getbits( cpinstruction, 12, 10 ), Getbits( cpinstruction, 9, 7 ) ); END; (* IF *) END; (* IF *) ELSE (* FMOVE from FPn, FMOVE FPcr, FMOVEM FPn, FMOVEM FPcr *) IF Getbits( cpinstruction, 15, 14 ) = 2 THEN (* FMOVE(M) FPcr *) Format43( mode, reg, Getbits( cpinstruction, 13, 13 ), Getbits( cpinstruction, 12, 10 ) ); ELSIF Getbits( cpinstruction, 15, 14 ) = 3 THEN (* FMOVEM FPn *) Format44( mode, reg, Getbits( cpinstruction, 13, 13 ), Getbits( cpinstruction, 11, 11 ), Getbits( cpinstruction, 7, 0 ) ); ELSIF Getbits( cpinstruction, 15, 13 ) = 3 THEN (* FMOVE from FPn *) Format45( mode, reg, Getbits( cpinstruction, 9, 7 ), Getbits( cpinstruction, 12, 10 ), Getbits( cpinstruction, 6, 0 ) ); ELSE WriteString( "illegal coprocessor instruction." ); END; (* IF *) END; (* IF *) | 1 : (* FDBcc, FScc, FTRAPcc *) ReadInt( cpinstruction ); CASE mode OF 1 : (* FDBcc *) Format46( reg, Getbits( cpinstruction, 5, 0 ) ); | 7 : (* FTRAPcc, FScc *) IF reg <= 1 THEN (* FScc *) Format47( mode, reg, Getbits( cpinstruction, 5, 0 ) ); ELSE (* FTRAPcc *) Format48( reg, Getbits( cpinstruction, 5, 0 ) ); END; (* IF *) ELSE (* FScc *) Format47( mode, reg, Getbits( cpinstruction, 5, 0 ) ); END; (* CASE *) | 2 : (* FBcc, FNOP *) IF Getbits( instruction, 5, 0 ) = 0 THEN (* FNOP *) ReadInt( cpinstruction ); WriteString( "FNOP" ); ELSE (* FBcc *) Format49( 0, Getbits( instruction, 5, 0 ) ); END; (* IF *) | 3 : (* FBcc *) Format49( 1, Getbits( instruction, 5, 0 ) ); | 4, 5 : (* FSAVE, FRESTORE *) Format50( Getbits( instruction, 8, 6 ), mode, reg ); | 6, 7 : WriteString( "illegal coprocessor instruction." ); END; (* CASE *) END; (* IF *) END CoprocessorDecode; PROCEDURE DecodeIns( instruction : INTEGER ); (* Decodes the given instruction and reads extension words if necessary. *) VAR size, mode, reg, op2 : INTEGER; BEGIN (* DecodeIns *) op2 := Getbits( instruction, 11, 9 ); size := Getbits( instruction, 7, 6 ); mode := Getbits( instruction, 5, 3 ); reg := Getbits( instruction, 2, 0 ); CASE Getbits( instruction, 15, 12 ) OF 0 : (* ADDI, ANDI, BCHG, BCLR, BSET, BTST, CALLM, CAS, CAS2, CHK2, CMPI, CMP2, EORI, MOVEP, MOVES, ORI, RTM, SUBI *) IF Getbits( instruction, 8, 8) = 0 THEN (* ADDI, ANDI, BCHG, BCLR, BSET, BTST, CALLM, CAS, CAS2, CHK2, CMPI, CMP2, EORI, MOVES, ORI, RTM, SUBI *) CASE op2 OF 0 : (* CHK2.B, CMP2.B, ORI *) IF size = 3 THEN (* CHK2.B, CMP2.B *) Format3( mode, reg, 0 ); ELSE (* ORI *) Format1( ORI, mode, reg, size ); END; (* IF *) | 1 : (* ANDI, CHK2.W, CMP2.W *) IF size = 3 THEN (* CHK2.W, CMP2.W *) Format3( mode, reg, 1 ); ELSE (* ANDI *) Format1( ANDI, mode, reg, size ); END; (* IF *) | 2 : (* CHK2.L, CMP2.L, SUBI *) IF size = other THEN (* CHK2.L, CMP2.L *) Format3( mode, reg, 2 ); ELSE (* SUBI *) Format1( SUBI, mode, reg, size ); END; (* IF *) | 3 : (* ADDI, CALLM, RTM *) IF size = other THEN (* CALLM, RTM *) IF Getbits( instruction, 5, 4 ) = 0 THEN (* RTM *) Format7( Getbits( instruction, 3, 3 ), reg ); ELSE (* CALLM *) Format8( mode, reg ); END; (* IF *) ELSE (* ADDI *) Format1( ADDI, mode, reg, size ); END; (* IF *) | 4 : (* BCHG, BCLR, BSET, BTST *) Format4( Getbits( instruction, 8, 6 ), mode, reg ); | 5 : (* CAS.B, EORI *) IF size = other THEN (* CAS.B *) Format5( mode, reg, 1 ); ELSE (* EORI *) Format1( EORI, mode, reg, size ); END; (* IF *) | 6 : (* CAS.W, CAS2.W, CMPI *) IF size = other THEN (* CAS.W, CAS2.W *) Format5( mode, reg, 2 ); ELSE (* CMPI *) Format1( CMPI, mode, reg, size ); END; (* IF *) | 7 : (* CAS.L, CAS2.L, MOVES *) IF size = other THEN (* CAS.L, CAS2.L *) Format5( mode, reg, 3 ); ELSE (* CMPI *) Format6( mode, reg, size ); END; (* IF *) END; (* CASE *) ELSE (* Bit 8 = 1: BCHG, BCLR, BSET, BTST, MOVEP *) IF mode = 1 THEN (* MOVEP *) Format9( op2, Getbits( instruction, 7, 7 ), Getbits( instruction, 6, 6 ), reg ); ELSE (* BCHG, BCLR, BSET, BTST *) Format10( size, op2, mode, reg ); END; (* IF *) END; (* IF *) | 1, 2, 3 : (* MOVE, MOVEA *) Format11( Getbits( instruction, 13, 12 ), mode, reg, Getbits( instruction, 8, 6 ), op2 ); | 4 : (* BKPT, CHK, CLR, DIVS, DIVSL, DIVU, DIVUL, EXT, EXTB, ILLEGAL, JMP, JSR, LEA, LINK, special MOVE, MOVEC, MOVEM, MULS, MULU, NBCD, NEG, NEGX, NOP, NOT, PEA, RESET, RTD, RTE, RTR, RTS, STOP, SWAP, TAS, TRAP, TRAPV, TST, UNLK *) CASE Getbits( instruction, 8, 6 ) OF 0 : (* CLR.B, LINK.L, MULS, MULU, NBCD, NEG.B, NEGX.B, NOT.B, TST.B *) CASE op2 OF 0, 1, 2, 3, 5 : (* NEGX.B, CLR.B, NEG.B, NOT.B, TST.B *) Format12( op2, 0, mode, reg ); | 4 : (* LINK.L, NBCD *) IF Getbits( instruction, 5, 3 ) = 1 THEN (* LINK.L *) Format13( 1, Getbits( instruction, 2, 0 ) ); ELSE (* NBCD *) Format14( NBCD, mode, reg ); END; (* IF *) | 6 : (* MULS, MULU *) Format29( MUL, mode, reg ); | 7 : WriteString( "illegal instruction." ); END; (* CASE *) | 1 : (* BKPT, CLR.W, DIVS, DIVSL, DIVU, DIVUL, LINK.W, MOVE USP, MOVEC, NEG.W, NEGX.W, NOP, NOT.W, PEA, RESET, RTD, RTE, RTR, RTS, STOP, SWAP, TRAP, TRAPV, TST.W, UNLK *) CASE op2 OF 0, 1, 2, 3, 5 : (* NEGX.W, CLR.W, NEG.W, NOT.W, TST.W *) Format12( op2, 1, mode, reg ); | 4 : (* BKPT, PEA, SWAP *) IF Getbits( instruction, 5, 3 ) <= 1 THEN (* SWAP, BKPT *) Format15( mode, reg ); ELSE (* PEA *) Format14( PEA, mode, reg ); END; (* IF *) | 6 : (* DIVS, DIVSL, DIVU, DIVUL *) Format29( dIV, mode, reg ); | 7 : (* LINK.W, MOVE USP, MOVEC, NOP, RESET, RTD, RTE, RTR, RTS, STOP, TRAP, TRAPV, UNLK *) CASE Getbits( instruction, 5, 3 ) OF 0, 1 : (* TRAP *) Format51( Getbits( instruction, 3, 0 ) ); | 2 : (* LINK.W *) Format13( 0, reg ); | 3 : (* UNLK *) Format15( 3, reg ); | 4 : (* MOVE to USP *) Format16( reg ); | 5 : (* MOVE from USP *) Format15( 4, reg ); | 6 : (* NOP, RESET, RTD, RTE, RTR, RTS, STOP, TRAPV *) CASE reg OF 0 : WriteString( "RESET" ); | 1 : WriteString( "NOP" ); | 2 : Format18( STOP ); | 3 : WriteString( "RTE" ); | 4 : Format18( RTD ); | 5 : WriteString( "RTS" ); | 6 : WriteString( "TRAPV" ); | 7 : WriteString( "RTR" ); END; (* CASE *) | 7 : (* MOVEC *) Format17( Getbits( instruction, 0, 0 ) ); END; (* CASE *) END; (* CASE *) | 2 : (* CLR.L, EXT.W, JSR, MOVEM.W, NEG.L, NEGX.L, NOT.L, TST.L *) CASE op2 OF 0, 1, 2, 3, 5 : (* NEGX.L, CLR.L, NEG.L, NOT.L, TST.L *) Format12( op2, size, mode, reg ); | 4 : (* EXT.W, MOVEM.W *) IF mode = 0 THEN (* EXT.W *) Format15( 5, reg ); ELSE (* MOVEM.W *) Format19( 0, 0, mode, reg ); END; (* IF *) | 6 : (* MOVEM.W *) Format19( 1, 0, mode, reg ); | 7 : (* JSR *) Format14( JSR, mode, reg ); END; (* CASE *) | 3 : (* EXT.L, ILLEGAL, JMP, MOVE CCR, MOVE SR, MOVEM.L, TAS *) CASE op2 OF 0, 1, 2, 3 : (* MOVE CCR, MOVE SR *) Format20( op2, mode, reg ); | 4 : (* EXT.L, MOVEM.L *) IF mode = 0 THEN (* EXT.L *) Format15( 6, reg ); ELSE (* MOVEM.L *) Format19( 0, 1, mode, reg ); END; (* IF *) | 5 : (* ILLEGAL, TAS *) IF Getbits( instruction, 5, 0 ) = 60 THEN (* ILLEGAL *) WriteString( "ILLEGAL" ); ELSE (* TAS *) Format14( TAS, mode, reg ); END; (* IF *) | 6 : (* MOVEM.L *) Format19( 1, 1, mode, reg ); | 7 : (* JMP *) Format14( JMP, mode, reg ); END; (* CASE *) | 4 : (* CHK.L *) Format21( 2, op2, mode, reg ); | 5 : WriteString( "illegal instruction." ); | 6 : (* CHK.W *) Format21( 1, op2, mode, reg ); | 7 : (* EXTB.L, LEA *) IF mode = 0 THEN (* EXTB.L *) Format15( 7, reg ); ELSE (* LEA *) Format22( op2, mode, reg ); END; (* IF *) END; (* CASE *) | 5 : (* ADDQ, DBcc, Scc, SUBQ, TRAPcc *) IF size = other THEN (* DBcc, Scc, TRAPcc *) CASE mode OF 1 : (* DBcc *) Format23( Getbits( instruction, 11, 8 ), reg ); | 7 : (* Scc, TRAPcc *) IF reg <= 1 THEN (* Scc *) Format24( Getbits( instruction, 11, 8 ), mode, reg ); ELSE (* TRAPcc *) Format25( Getbits( instruction, 11, 8 ), reg ); END; (* IF *) ELSE (* Scc *) Format24( Getbits( instruction, 11, 8 ), mode, reg ); END; (* CASE *) ELSE (* ADDQ, SUBQ *) Format26( Getbits( instruction, 8, 8 ), op2, size, mode, reg ); END; (* IF *) | 6 : (* Bcc, BRA, BSR *) Format27( Getbits( instruction, 11, 8 ), Getbits( instruction, 7, 0 ) ); | 7 : (* MOVEQ *) Format28( op2, Getbits( instruction, 7, 0 ) ); | 8 : (* DIVS, DIVU, OR, PACK, SBCD, UNPK *) CASE Getbits( instruction, 8, 6 ) OF 0, 1, 2 : (* OR *) Format31( oR, 0, op2, size, mode, reg ); | 3 : (* DIVU *) Format30( dIV, 0, op2, mode, reg ); | 4 : (* OR, SBCD *) IF Getbits( instruction, 5, 4 ) = 0 THEN (* SBCD *) Format32( SBCD, 0, Getbits( instruction, 3, 3 ), reg, op2 ); ELSE (* OR *) Format31( oR, 1, op2, 0, mode, reg ); END; (* IF *) | 5 : (* OR, PACK *) IF Getbits( instruction, 5, 4 ) = 0 THEN (* PACK *) Format33( PACK, Getbits( instruction, 3, 3 ), reg, op2 ); ELSE (* OR *) Format31( oR, 1, op2, 1, mode, reg ); END; (* IF *) | 6 : (* OR, UNPK *) IF Getbits( instruction, 5, 4 ) = 0 THEN (* UNPK *) Format33( UNPK, Getbits( instruction, 3, 3 ), reg, op2 ); ELSE (* OR *) Format31( oR, 1, op2, 2, mode, reg ); END; (* IF *) | 7 : (* DIVS *) Format30( dIV, 1, op2, mode, reg ); END; (* CASE *) | 9 : (* SUB, SUBA, SUBX *) IF size = 3 THEN (* SUBA *) Format34( SUBA, Getbits( instruction, 8, 8 ), op2, mode, reg ); ELSE (* SUB, SUBX *) IF ( Getbits( instruction, 8, 8 ) = 1 ) & ( Getbits( instruction, 5, 4 ) = 0 ) THEN (* SUBX *) Format32( SUBX, size, Getbits( instruction, 3, 3 ), reg, op2 ); ELSE (* SUB *) Format31( SUB, Getbits( instruction, 8, 8 ), op2, size, mode, reg ); END; (* IF *) END; (* IF *) | 10 : WriteString( "illegal instruction." ); | 11 : (* CMP, CMPA, CMPM, EOR *) CASE Getbits( instruction, 8, 6 ) OF 0, 1, 2 : (* CMP *) Format31( CMP, 0, op2, size, mode, reg ); | 3, 7 : (* CMPA *) Format34( CMPA, Getbits( instruction, 8, 8 ), op2, mode, reg ); | 4, 5, 6 : (* CMPM, EOR *) IF Getbits( instruction, 5, 3 ) = 1 THEN (* CMPM *) Format35( size, op2, reg ); ELSE (* EOR *) Format31( EOR, 1, op2, size, mode, reg ); END; (* IF *) END; (* CASE *) | 12 : (* ABCD, AND, EXG, MULS, MULU *) CASE Getbits( instruction, 8, 6 ) OF 0, 1, 2 : (* AND *) Format31( AND, 0, op2, size, mode, reg ); | 3 : (* MULU *) Format30( MUL, 0, op2, mode, reg ); | 4 : (* ABCD, AND.B *) IF Getbits( instruction, 5, 4 ) = 0 THEN (* ABCD *) Format32( ABCD, 0, Getbits( instruction, 3, 3 ), reg, op2 ); ELSE (* AND.B *) Format31( AND, 1, op2, 0, mode, reg ); END; (* IF *) | 5 : (* AND.W, EXG *) IF Getbits( instruction, 5, 4 ) = 0 THEN (* EXG *) Format36( Getbits( instruction, 7, 3 ), op2, reg ); ELSE (* AND.W *) Format31( AND, 1, op2, 1, mode, reg ); END; (* IF *) | 6 : (* AND.L, EXG *) IF Getbits( instruction, 5, 4 ) = 0 THEN (* EXG *) Format36( Getbits( instruction, 7, 3 ), op2, reg ); ELSE (* AND.L *) Format31( AND, 1, op2, 2, mode, reg ); END; (* IF *) | 7 : (* MULS *) Format30( MUL, 1, op2, mode, reg ); END; (* CASE *) | 13 : (* ADD, ADDA, ADDX *) IF size = other THEN (* ADDA *) Format34( ADDA, Getbits( instruction, 8, 8 ), op2, mode, reg ); ELSE (* ADD, ADDX *) IF ( Getbits( instruction, 8, 8 ) = 1 ) & ( Getbits( instruction, 5, 4 ) = 0 ) THEN (* ADDX *) Format32( ADDX, size, Getbits( instruction, 3, 3 ), reg, op2 ); ELSE (* ADD *) Format31( ADD, Getbits( instruction, 8, 8 ), op2, size, mode, reg ); END; (* IF *) END; (* IF *) | 14 : (* ASL, ASR, BFCHG, BFCLR, BFEXTS, BFEXTU, BFFFO, BFINS, BFSET, BFTST, LSL, LSR, ROL, ROR, ROXL, ROXR *) IF size = other THEN (* bit field operations, memory shifts and rotates *) CASE Getbits( instruction, 11, 8 ) OF 0 : (* ASR *) Format14( ASR, mode, reg ); | 1 : (* ASL *) Format14( ASL, mode, reg ); | 2 : (* LSR *) Format14( LSR, mode, reg ); | 3 : (* LSL *) Format14( LSL, mode, reg ); | 4 : (* ROXR *) Format14( ROXR, mode, reg ); | 5 : (* ROXL *) Format14( ROXL, mode, reg ); | 6 : (* ROR *) Format14( ROR, mode, reg ); | 7 : (* ROL *) Format14( ROL, mode, reg ); | 8 : (* BFTST *) Format37( BFTST, mode, reg ); | 9 : (* BFEXTU *) Format38( BFEXTU, mode, reg ); | 10 : (* BFCHG *) Format37( BFCHG, mode, reg ); | 11 : (* BFEXTS *) Format38( BFEXTS, mode, reg ); | 12 : (* BFCLR *) Format37( BFCLR, mode, reg ); | 13 : (* BFFFO *) Format38( BFFFO, mode, reg); | 14 : (* BFSET *) Format37( BFSET, mode, reg ); | 15 : (* BFINS *) Format2( mode, reg ); END; (* CASE *) ELSE (* register shifts and rotates *) Format39( Getbits( instruction, 4, 3 ), op2, Getbits( instruction, 8, 8 ), size, Getbits( instruction, 5, 5 ), reg ); END; (* IF *) | 15 : (* coprocessor *) CoprocessorDecode( instruction, mode, reg ); END; (* CASE *) END DecodeIns; PROCEDURE ReadHeader( VAR entries, commands, pointers, imports : INTEGER; VAR constSize, codeSize, refLen : LONGINT; VAR error : BOOLEAN ); (* Reads the header block and writes the information to the output. *) VAR ch : CHAR; link : INTEGER; modName : ARRAY 24 OF CHAR; key, dsize, refPos : LONGINT; BEGIN (* ReadHeader *) Read( ch ); IF ch # 0F1X THEN WriteString( "No object file." ); error := TRUE; ELSE Read( ch ); ReadLongint( refPos ); ReadLongint( refLen ); ReadInt( entries ); ReadInt( commands ); ReadInt( pointers ); ReadInt( imports ); ReadInt( link ); ReadLongint( dsize ); ReadLongint( constSize ); ReadLongint( codeSize ); ReadLongint( key ); ReadString( modName, 24 ); WriteString( "Module: " ); WriteString( modName ); WriteLn; WriteString( "Key: " ); WriteInt( key ); WriteLn; WriteLn; WriteString( "Link: " ); WriteInt( link ); WriteLn; WriteLn; WriteString( "Data size: " ); WriteInt( dsize ); WriteLn; WriteLn; Texts.Append( output, writer.buf ); END; (* IF *) END ReadHeader; PROCEDURE ReadEntries( entries : INTEGER; VAR error : BOOLEAN ); (* Reads the enties from the file and writes them to the output. *) VAR i : INTEGER; ch : CHAR; entry : LONGINT; BEGIN (* ReadEntries *) IF ~ error THEN WriteString( "Entries: " ); Read( ch ); IF ch # 82X THEN WriteString( BlockMisaligned ); WriteLn; error := TRUE; ELSE WriteInt( entries ); WriteLn; FOR i := 0 TO entries - 1 DO ReadLongint( entry ); WriteInt( entry ); WriteLn; END; (* FOR *) WriteLn; END; (* IF *) END; (* IF *) Texts.Append( output, writer.buf ); END ReadEntries; PROCEDURE ReadCommands( commands : INTEGER; VAR error : BOOLEAN ); (* Reads the commands from the file and writes them to the output. *) VAR i : INTEGER; ch : CHAR; name : ARRAY 100 OF CHAR; entry : LONGINT; BEGIN (* ReadCommands *) IF ~ error THEN WriteString( "Commands: " ); Read( ch ); IF ch # 83X THEN WriteString( BlockMisaligned ); WriteLn; error := TRUE; ELSE WriteInt( commands ); WriteLn; FOR i := 0 TO commands - 1 DO ReadString( name, 0 ); WriteString( name ); WriteString( ": " ); ReadLongint( entry ); WriteInt( entry ); WriteLn; END; (* FOR *) WriteLn; END; (* IF *) END; (* IF *) Texts.Append( output, writer.buf ); END ReadCommands; PROCEDURE ReadPointers( pointers : INTEGER; VAR error : BOOLEAN ); (* Reads the global pointers from the file and writes them to the output. *) VAR i : INTEGER; ch : CHAR; adr : LONGINT; BEGIN (* ReadPointers *) IF ~ error THEN WriteString( "Pointers: " ); Read( ch ); IF ch # 84X THEN WriteString( BlockMisaligned ); WriteLn; error := TRUE; ELSE WriteInt( pointers ); WriteLn; FOR i := 0 TO pointers - 1 DO ReadLongint( adr ); WriteInt( adr ); WriteLn; END; (* FOR *) WriteLn; END; (* IF *) END; (* IF *) Texts.Append( output, writer.buf ); END ReadPointers; PROCEDURE ReadImports( imports : INTEGER; VAR error : BOOLEAN ); (* Reads the imports from the file and writes them to the output. *) VAR i : INTEGER; ch : CHAR; name : ARRAY 30 OF CHAR; adr : LONGINT; BEGIN (* ReadImports *) IF ~ error THEN WriteString( "Imports: " ); Read( ch ); IF ch # 85X THEN WriteString( BlockMisaligned ); WriteLn; error := TRUE; ELSE WriteInt( imports ); WriteLn; FOR i := 0 TO imports - 1 DO ReadLongint( adr ); ReadString( name, 0 ); WriteString( name ); WriteString( ": " ); WriteInt( adr ); WriteLn; END; (* FOR *) WriteLn; END; (* IF *) END; (* IF *) Texts.Append( output, writer.buf ); END ReadImports; PROCEDURE ReadConst( size : LONGINT; VAR error : BOOLEAN ); (* Reads the constants from the file and writes them in decimal format to the output. *) VAR i : LONGINT; ch : CHAR; BEGIN (* ReadConst *) IF ~ error THEN WriteString( "Constants: " ); Read( ch ); IF ch # 86X THEN WriteString( BlockMisaligned ); WriteLn; error := TRUE; ELSE WriteInt( size ); WriteLn; FOR i := 0 TO size - 1 DO Read( ch ); WriteInt( ORD( ch ) ); Write( " " ); IF i MOD 20 = 19 THEN WriteLn; END; END; (* FOR *) WriteLn; WriteLn; END; (* IF *) END; (* IF *) Texts.Append( output, writer.buf ); END ReadConst; PROCEDURE ReadCode( size : LONGINT; VAR error : BOOLEAN ); (* Reads the code from the file and decodes it to the output. *) VAR ch : CHAR; instruction : INTEGER; BEGIN (* ReadCode *) IF ~ error THEN WriteString( "Code: " ); Read( ch ); IF ch # 87X THEN WriteString( BlockMisaligned ); WriteLn; error := TRUE; ELSE WriteInt( size ); WriteLn; pc := 0; REPEAT WriteInt( pc ); WriteString( " " ); ReadInt( instruction ); DecodeIns( instruction ); WriteLn; Texts.Append( output, writer.buf ); UNTIL pc >= size; WriteLn; END; (* IF *) END; (* IF *) Texts.Append( output, writer.buf ); END ReadCode; PROCEDURE ReadRef( VAR error : BOOLEAN ); (* Reads the reference information from the file. *) VAR adr : LONGINT; ch : CHAR; name : ARRAY 256 OF CHAR; BEGIN (* ReadRef *) IF ~ error THEN WriteString( "References: " ); Read( ch ); IF ch # 88X THEN WriteString( BlockMisaligned ); WriteLn; error := TRUE; ELSE WriteLn; Read( ch ); ReadDynint( adr ); WHILE ~rider.eof DO WriteString( "Procedure: " ); ReadString( name, 0 ); WriteString( name ); WriteString( " " ); WriteInt( adr ); WriteLn; Read( ch ); WHILE ( ~rider.eof ) & ( ch # 0F8X ) DO IF ch = 1X THEN WriteString( " Variable: " ); ELSE WriteString( " Var-Parameter: " ); END; Read( ch ); ReadDynint( adr ); ReadString( name, 0 ); WriteString( name ); WriteType( ch ); WriteInt( adr ); WriteLn; Read( ch ); END; (* WHILE *) ReadDynint( adr ); END; (* WHILE *) END; (* IF *) END; (* IF *) Texts.Append( output, writer.buf ); END ReadRef; PROCEDURE Decode*; (* Translates the code in the file after the call into a viewer. *) VAR vx, vy : INTEGER; entries, commands, pointers, imports : INTEGER; constSize, codeSize, refLen : LONGINT; error : BOOLEAN; beg, end, time: LONGINT; text : Texts.Text; BEGIN (* Disassemble *) Texts.OpenScanner( scanner, Oberon.Par.text, Oberon.Par.pos ); Texts.Scan( scanner ); IF ( scanner.class = Texts.Char ) & ( scanner.c = "^" ) OR ( scanner.line # 0 ) THEN Oberon.GetSelection( text, beg, end, time ); IF time >= 0 THEN Texts.OpenScanner( scanner, text, beg ); Texts.Scan( scanner ) END END; IF scanner.class = Texts.Name THEN file := Files.Old( scanner.s ); IF file = NIL THEN Texts.OpenWriter( writer ); Texts.WriteString( writer, "File not found: '" ); Texts.WriteString( writer, scanner.s ); Texts.Write( writer, "'" ); Texts.WriteLn( writer ); Texts.Append( Oberon.Log, writer.buf ); ELSE Files.Set( rider, file, 0 ); NEW( output ); Texts.Open( output, "" ); output.notify := TextFrames.NotifyDisplay; frame := TextFrames.NewText( output, 0 ); Oberon.AllocateUserViewer( Oberon.Par.vwr.X, vx, vy ); NEW( viewer ); viewer := MenuViewers.New( TextFrames.NewMenu( "AsmCode", "System.Close System.Copy System.Grow Edit.Search Edit.Store" ), frame, TextFrames.menuH, vx, vy ); Texts.OpenWriter( writer ); error := FALSE; ReadHeader( entries, commands, pointers, imports, constSize, codeSize, refLen, error ); ReadEntries( entries, error ); ReadCommands( commands, error ); ReadPointers( pointers, error ); ReadImports( imports, error ); ReadConst( constSize, error ); ReadCode( codeSize, error ); ReadRef( error ); END; (* IF *) END; (* IF *) END Decode; END Decoder.