MODULE ORTool; (*NW 18.2.2013*) IMPORT SYSTEM, Files, Texts, Oberon, ORB; VAR W: Texts.Writer; Form: INTEGER; (*result of ReadType*) mnemo0, mnemo1: ARRAY 16, 4 OF CHAR; (*mnemonics*) PROCEDURE Read(VAR R: Files.Rider; VAR n: INTEGER); VAR b: BYTE; BEGIN Files.ReadByte(R, b); IF b < 80H THEN n := b ELSE n := b - 100H END END Read; PROCEDURE ReadType(VAR R: Files.Rider); VAR key, len, lev, size, off: INTEGER; ref, mno, class, form, readonly: INTEGER; name, modname: ARRAY 32 OF CHAR; BEGIN Read(R, ref); Texts.Write(W, " "); Texts.Write(W, "["); IF ref < 0 THEN Texts.Write(W, "^"); Texts.WriteInt(W, -ref, 1) ELSE Texts.WriteInt(W, ref, 1); Read(R, form); Texts.WriteString(W, " form = "); Texts.WriteInt(W, form, 1); IF form = ORB.Pointer THEN ReadType(R) ELSIF form = ORB.Array THEN ReadType(R); Files.ReadNum(R, len); Files.ReadNum(R, size); Texts.WriteString(W, " len = "); Texts.WriteInt(W, len, 1); Texts.WriteString(W, " size = "); Texts.WriteInt(W, size, 1) ELSIF form = ORB.Record THEN ReadType(R); (*base type*) Files.ReadNum(R, off); Texts.WriteString(W, " exno = "); Texts.WriteInt(W, off, 1); Files.ReadNum(R, off); Texts.WriteString(W, " extlev = "); Texts.WriteInt(W, off, 1); Files.ReadNum(R, size); Texts.WriteString(W, " size = "); Texts.WriteInt(W, size, 1); Texts.Write(W, " "); Texts.Write(W, "{"); Read(R, class); WHILE class # 0 DO (*fields*) Files.ReadString(R, name); IF name[0] # 0X THEN Texts.Write(W, " "); Texts.WriteString(W, name); ReadType(R) ELSE Texts.WriteString(W, " --") END ; Files.ReadNum(R, off); Texts.WriteInt(W, off, 4); Read(R, class) END ; Texts.Write(W, "}") ELSIF form = ORB.Proc THEN ReadType(R); Texts.Write(W, "("); Read(R, class); WHILE class # 0 DO Texts.WriteString(W, " class = "); Texts.WriteInt(W, class, 1); Read(R, readonly); IF readonly = 1 THEN Texts.Write(W, "#") END ; ReadType(R); Read(R, class) END ; Texts.Write(W, ")") END ; Files.ReadString(R, modname); IF modname[0] # 0X THEN Files.ReadInt(R, key); Files.ReadString(R, name); Texts.Write(W, " "); Texts.WriteString(W, modname); Texts.Write(W, "."); Texts.WriteString(W, name); Texts.WriteHex(W, key) END END ; Form := form; Texts.Write(W, "]") END ReadType; PROCEDURE DecSym*; (*decode symbol file*) VAR class, typno, k: INTEGER; name: ARRAY 32 OF CHAR; F: Files.File; R: Files.Rider; S: Texts.Scanner; BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S); IF S.class = Texts.Name THEN Texts.WriteString(W, "OR-decode "); Texts.WriteString(W, S.s); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); F := Files.Old(S.s); IF F # NIL THEN Files.Set(R, F, 0); Files.ReadInt(R, k); Files.ReadInt(R, k); Files.ReadString(R, name); Texts.WriteString(W, name); Texts.WriteHex(W, k); Read(R, class); Texts.WriteInt(W, class, 3); (*sym file version*) IF class = ORB.versionkey THEN Texts.WriteLn(W); Read(R, class); WHILE class # 0 DO Texts.WriteInt(W, class, 4); Files.ReadString(R, name); Texts.Write(W, " "); Texts.WriteString(W, name); ReadType(R); IF class = ORB.Typ THEN Texts.Write(W, "("); Read(R, class); WHILE class # 0 DO (*pointer base fixup*) Texts.WriteString(W, " ->"); Texts.WriteInt(W, class, 4); Read(R, class) END ; Texts.Write(W, ")") ELSIF (class = ORB.Const) OR (class = ORB.Var) THEN Files.ReadNum(R, k); Texts.WriteInt(W, k, 5); (*Reals, Strings!*) END ; Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); Read(R, class) END ELSE Texts.WriteString(W, " bad symfile version") END ELSE Texts.WriteString(W, " not found") END ; Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf) END END DecSym; (* ---------------------------------------------------*) PROCEDURE WriteReg(r: LONGINT); BEGIN Texts.Write(W, " "); IF r < 12 THEN Texts.WriteString(W, " R"); Texts.WriteInt(W, r MOD 10H, 1) ELSIF r = 12 THEN Texts.WriteString(W, "MT") ELSIF r = 13 THEN Texts.WriteString(W, "SB") ELSIF r = 14 THEN Texts.WriteString(W, "SP") ELSE Texts.WriteString(W, "LNK") END END WriteReg; PROCEDURE opcode(w: LONGINT); VAR k, op, u, a, b, c: LONGINT; BEGIN k := w DIV 40000000H MOD 4; a := w DIV 1000000H MOD 10H; b := w DIV 100000H MOD 10H; op := w DIV 10000H MOD 10H; u := w DIV 20000000H MOD 2; IF k = 0 THEN Texts.WriteString(W, mnemo0[op]); IF u = 1 THEN Texts.Write(W, "'") END ; WriteReg(a); WriteReg(b); WriteReg(w MOD 10H) ELSIF k = 1 THEN Texts.WriteString(W, mnemo0[op]); IF u = 1 THEN Texts.Write(W, "'") END ; WriteReg(a); WriteReg(b); w := w MOD 10000H; IF w >= 8000H THEN w := w - 10000H END ; Texts.WriteInt(W, w, 7) ELSIF k = 2 THEN (*LDR/STR*) IF u = 1 THEN Texts.WriteString(W, "STR ") ELSE Texts.WriteString(W, "LDR") END ; WriteReg(a); WriteReg(b); w := w MOD 100000H; IF w >= 80000H THEN w := w - 100000H END ; Texts.WriteInt(W, w, 8) ELSIF k = 3 THEN (*Branch instr*) Texts.Write(W, "B"); IF ODD(w DIV 10000000H) THEN Texts.Write(W, "L") END ; Texts.WriteString(W, mnemo1[a]); IF u = 0 THEN WriteReg(w MOD 10H) ELSE w := w MOD 100000H; IF w >= 80000H THEN w := w - 100000H END ; Texts.WriteInt(W, w, 8) END END END opcode; PROCEDURE Sync(VAR R: Files.Rider); VAR ch: CHAR; BEGIN Files.Read(R, ch); Texts.WriteString(W, "Sync "); Texts.Write(W, ch); Texts.WriteLn(W) END Sync; PROCEDURE Write(VAR R: Files.Rider; x: INTEGER); BEGIN Files.WriteByte(R, x) (* -128 <= x < 128 *) END Write; PROCEDURE DecObj*; (*decode object file*) VAR class, i, n, key, size, fix, adr, data, len: INTEGER; ch: CHAR; name: ARRAY 32 OF CHAR; F: Files.File; R: Files.Rider; S: Texts.Scanner; BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S); IF S.class = Texts.Name THEN Texts.WriteString(W, "decode "); Texts.WriteString(W, S.s); F := Files.Old(S.s); IF F # NIL THEN Files.Set(R, F, 0); Files.ReadString(R, name); Texts.WriteLn(W); Texts.WriteString(W, name); Files.ReadInt(R, key); Texts.WriteHex(W, key); Read(R, class); Texts.WriteInt(W, class, 4); (*version*) Files.ReadInt(R, size); Texts.WriteInt(W, size, 6); Texts.WriteLn(W); Texts.WriteString(W, "imports:"); Texts.WriteLn(W); Files.ReadString(R, name); WHILE name[0] # 0X DO Texts.Write(W, 9X); Texts.WriteString(W, name); Files.ReadInt(R, key); Texts.WriteHex(W, key); Texts.WriteLn(W); Files.ReadString(R, name) END ; (* Sync(R); *) Texts.WriteString(W, "type descriptors"); Texts.WriteLn(W); Files.ReadInt(R, n); n := n DIV 4; i := 0; WHILE i < n DO Files.ReadInt(R, data); Texts.WriteHex(W, data); INC(i) END ; Texts.WriteLn(W); Texts.WriteString(W, "data"); Files.ReadInt(R, data); Texts.WriteInt(W, data, 6); Texts.WriteLn(W); Texts.WriteString(W, "strings"); Texts.WriteLn(W); Files.ReadInt(R, n); i := 0; WHILE i < n DO Files.Read(R, ch); Texts.Write(W, ch); INC(i) END ; Texts.WriteLn(W); Texts.WriteString(W, "code"); Texts.WriteLn(W); Files.ReadInt(R, n); i := 0; WHILE i < n DO Files.ReadInt(R, data); Texts.WriteInt(W, i, 4); Texts.Write(W, 9X); Texts.WriteHex(W, data); Texts.Write(W, 9X); opcode(data); Texts.WriteLn(W); INC(i) END ; (* Sync(R); *) Texts.WriteString(W, "commands:"); Texts.WriteLn(W); Files.ReadString(R, name); WHILE name[0] # 0X DO Texts.Write(W, 9X); Texts.WriteString(W, name); Files.ReadInt(R, adr); Texts.WriteInt(W, adr, 5); Texts.WriteLn(W); Files.ReadString(R, name) END ; (* Sync(R); *) Texts.WriteString(W, "entries"); Texts.WriteLn(W); Files.ReadInt(R, n); i := 0; WHILE i < n DO Files.ReadInt(R, adr); Texts.WriteInt(W, adr, 6); INC(i) END ; Texts.WriteLn(W); (* Sync(R); *) Texts.WriteString(W, "pointer refs"); Texts.WriteLn(W); Files.ReadInt(R, adr); WHILE adr # -1 DO Texts.WriteInt(W, adr, 6); Files.ReadInt(R, adr) END ; Texts.WriteLn(W); (* Sync(R); *) Files.ReadInt(R, data); Texts.WriteString(W, "fixP = "); Texts.WriteInt(W, data, 8); Texts.WriteLn(W); Files.ReadInt(R, data); Texts.WriteString(W, "fixD = "); Texts.WriteInt(W, data, 8); Texts.WriteLn(W); Files.ReadInt(R, data); Texts.WriteString(W, "fixT = "); Texts.WriteInt(W, data, 8); Texts.WriteLn(W); Files.ReadInt(R, data); Texts.WriteString(W, "entry = "); Texts.WriteInt(W, data, 8); Texts.WriteLn(W); Files.Read(R, ch); IF ch # "O" THEN Texts.WriteString(W, "format eror"); Texts.WriteLn(W) END (* Sync(R); *) ELSE Texts.WriteString(W, " not found"); Texts.WriteLn(W) END ; Texts.Append(Oberon.Log, W.buf) END END DecObj; BEGIN Texts.OpenWriter(W); Texts.WriteString(W, "ORTool 18.2.2013"); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); mnemo0[0] := "MOV"; mnemo0[1] := "LSL"; mnemo0[2] := "ASR"; mnemo0[3] := "ROR"; mnemo0[4] := "AND"; mnemo0[5] := "ANN"; mnemo0[6] := "IOR"; mnemo0[7] := "XOR"; mnemo0[8] := "ADD"; mnemo0[9] := "SUB"; mnemo0[10] := "MUL"; mnemo0[11] := "DIV"; mnemo0[12] := "FAD"; mnemo0[13] := "FSB"; mnemo0[14] := "FML"; mnemo0[15] := "FDV"; mnemo1[0] := "MI "; mnemo1[8] := "PL"; mnemo1[1] := "EQ "; mnemo1[9] := "NE "; mnemo1[2] := "LS "; mnemo1[10] := "HI "; mnemo1[5] := "LT "; mnemo1[13] := "GE "; mnemo1[6] := "LE "; mnemo1[14] := "GT "; mnemo1[15] := "NO "; END ORTool.