! This is what I had to do to the program below to make it compile under Imp80 ! No %predicate, %true, %false ! No stand-alone %else or %else %if (needs %finish ... %start around it) ! No continuation from line ending in - ! string concatenation - line ending in . is not automatically joined ! Can't do s = s.nl - must do s = s.snl - i.e. char not hoisted to string ! Can't have external routines before a main program ! BYTE(addr) should be BYTEINTEGER(addr) ! declarations must be at the head of a %begin block - ! not after a %start for instance ! guts <- guts." " ! is marked as an "unproductive logical operation" - I was padding the ! string which had a max length of 255. It really should have been OK ! and was doing something useful. ! Of course, this program doesn't run on anything except the Archimedes ! because it's purpose is to do a disassembly of the system rom, which is ! in store - it doesn't work from a file. ! (Look for Module Header == RECORD(from) ) ! Consequently it gives a nice Imp "address error" and backtrace when ! it executes. %begin !%external %string (255) %fn %spec cli param %const %integer TRUE = 0, FALSE = 1 %const %integer blocked=0, avail=1 %external %string(255) %fn %spec ItoS(%integer i, pl) %string(255) %fn ItoH(%integer i, pl) %constbytearray HexByte(0:15) = '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' %integer shift %string(255) s; s = "" %for shift = 0, 4, pl*4-4 %cycle s = tostring(HexByte((i>>shift)&15)).s %repeat %result = s %end %const %integer %C Def Inst = 1, { Instruction } Def Byte = 2, { = byte } Def Char = 4, { = "chars" } Def Word = 8, { EQUD word } Def Labelled = 16, {DATA ... } Def Branch Dest = 32, {LAB ... } Def Call Dest = 64, {PROC ... } Def Access = 128 { B somewhere } %string(255) %fn Instr Decode(%integer Pc, N) %integer CC, Type, Op, Rn, Rd, Shf, Shift, Imm, Offset, Operand %integer X, Y, Z, Printed; Printed = 0 %string(1) Sign %switch F(0:7), Fm(0:31) %conststring(3)%array Fn(0:15) = "AND", "EOR", "SUB", "RSB", "ADD", "ADC", "SBC", "RSC", "TST", "TEQ", "CMP", "CMN", "ORR", "MOV", "BIC", "MVN" %conststring(2)%array Cond(0:15) = "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV" %string(255) result string; result string = "" %routine Print string(%string(255) s) result string = result string.s %end %routine space result string = result string." " %end %routine spaces(%integer n) result string = result string." " %for n = 1,1,n %end %routine print hex(%integer i, pl) result string = result string.itoh(i, pl) %end %routine print symbol(%integer i) result string = result string.tostring(i) %end %routine Write(%integer i, pl) result string = result string.itos(i, pl) %end %routine Register(%integer N) %if N = 15 %start Printstring("PC") %finish %else %start Printsymbol('R') Write(N, 0) %finish %end %routine F Register(%integer N) Printsymbol('F') Write(N, 0) %end %routine Put(%string(255) S) Printstring(S) Printed = Printed+Length(S) %end %routine Show Label(%integer N) Printstring("L") Print Hex(N, 8) %end %routine Show Hex(%integer N, P) Printstring("&") Print Hex(N, P) %end %routine Show Shift(%integer Shift, Reg) %integer X, Y, Rs %string(3) S %switch Sh(0:7) Register(Reg) %return %if Shift = 0 Y = Shift>>3 X = Shift&7 Space ->Sh(X) Sh(1): S = "LSL"; ->Sh2 Sh(3): S = "LSR"; ->Sh2 Sh(5): S = "ASR"; ->Sh2 Sh(7): S = "ROR"; ->Sh2 Sh2: Rs = Shift>>4 Printstring(S); Space; Register(Rs); %return Sh(0): S = "LSL"; ->Sh1 Sh(2): S = "LSR"; ->Sh1 Sh(4): S = "ASR"; ->Sh1 Sh(6): S = "ROR"; S = "" %if Y = 0 Sh1: %if S = "" %start Printstring("RRX") %finish %else %start Printstring(S); Printstring(" #"); Write(Y, 0) %finish %end %routine Show Constreg(%integer N) %integer X X = N&7 %if N&8 = 0 %start F Register(X) %finish %else %start %if X <= 5 %start Write(X, 0); Printstring(".0") %finish %else %if X = 6 %start Printstring("0.5") %finish %else %start Printstring("10.0") %finish %finish %end Printed = 0 CC = N>>28 Type = N>>25&7 Rd = (N>>12)&15 Rn = (N>>16)&15 ->F(Type) F(2_000): F(2_001): Op = (N>>21)&15 Shf = (N>>8)&15 Shift = (N>>4)&255 Put(Fn(Op)); Put(Cond(CC)) Put("S") %if N&2_0000 000 0000 1 0000 0000 000000000000 # 0 Put("P") %if Rd = 15 %and 8 <= Op <= 11 Spaces(8-Printed) Register(Rd) %and Printstring(", ") %unless 8 <= Op <= 11 Register(Rn) %and Printstring(", ") %if Op # 13 %and Op # 15 %if N&16_0200 0000 # 0 %start {Shf Imm} X = 2*Shf Imm = N&255 %if X > 8 %start X = X-8 Y = (Imm<<24)>>X %finish %else %start Y = (Imm<<(32-X)) ! (Imm>>X) %finish Printstring("#") %if -16_FFFF <= Y <= 16_FFFF %start %if ' ' <= Y <= 126 %start Write(Y, 0) Printstring("; '") Printsymbol(Y) Printsymbol('''') %finish %else %start Write(Y, 0) %finish %finish %else %start Show Hex(Y, 8) %finish %finish %else %start {Shift Rm} Show Shift(Shift, N&15) %finish ->Done F(2_010): F(2_011): Type = N>>24&15 %if N&16_0010 0000 = 0 %then Put("STR") %else Put("LDR") Put(Cond(CC)) Put("B") %if N&16_0040 0000 # 0 Put("T") %if N&16_0020 0000 # 0 %and Type&1 = 0 Spaces(8-Printed) Register(Rd) Printstring(", ") Offset = N&4095 Sign = ""; Sign = "-" %if N&16_0080 0000 = 0 Printsymbol('['); Register(Rn) %if Type = 2_0100 %start Printsymbol(']') %if Offset # 0 %start Printstring(", #"); Printstring(Sign); Show Hex(Offset, 3) %finish %finish %else %if Type = 2_0101 %start %if Offset # 0 %start Printstring(", #"); Printstring(Sign); Show Hex(Offset, 3) %finish Printsymbol(']') Printsymbol('!') %if N&16_0020 0000 # 0 %finish %else %if Type = 2_0110 %start Printstring("]") %if Offset # 0 %start Printstring(", ") Printstring(Sign) Show Shift(Offset>>4, N&15) %finish %finish %else {%if Type = 2_0111} %start Printsymbol(',') Printstring(Sign) Show Shift(Offset>>4, N&15) Printsymbol(']') Printsymbol('!') %if N&16_0020 0000 # 0 %and Offset # 0 %finish ->Done F(2_100): %if N&16_0010 0000 = 0 %then Put("STM") %else Put("LDM") Put(Cond(CC)) X = N>>23&3 %if X&1 # 0 %then Put("I") %else Put("D") %if X&2 # 0 %then Put("B") %else Put("A") Spaces(8-Printed) Register(Rn) Printsymbol('!') %if N&16_0020 0000 # 0 Y = 1 Z = 1 Printstring(", {") %for X = 0, 1, 15 %cycle %if N&Y # 0 %start Printsymbol(',') %if Z = 0 Register(X) Z = 0 %finish Y = Y<<1 %repeat Printsymbol('}') Printsymbol('^') %if N&16_0040 0000 # 0 ->Done F(2_101): Put("B"); Put("L") %if N&16_0100 0000 # 0 Put(Cond(CC)) Spaces(8-Printed) X = N&16_00FF FFFF X = X!16_FF00 0000 %if X&16_0080 0000 # 0 Show Label(Pc+(2+X)*4) ->Done F(2_110): %if N&16_0010 0000 = 0 %then Put("STF") %else Put("LDF") Put(Cond(CC)) %if N&16_0040 0000 = 0 %start %if N&16_0000 8000 = 0 %then Put("S") %else Put("D") %finish %else %start %if N&16_0000 8000 = 0 %then Put("E") %else Put("P") %finish Spaces(8-Printed) F Register(N>>12&7) Printstring(", [") Register(N>>16&15) X = (N&255)<<2 %if N&16_0100 0000 = 0 %start Printstring("]") %if X # 0 %start Printstring(", #") Printsymbol('-') %if N&16_0080 0000 = 0 Show Hex(X, 3) %finish %finish %else %start %if X # 0 %start Printstring(", #") Printsymbol('-') %if N&16_0080 0000 = 0 Show Hex(X, 3) %finish Printstring("]") %finish Printsymbol('!') %if N&16_0020 0000 # 0 ->Done F(2_111): %if N&16_0100 0000 # 0 %start Put("SWI"); Put(Cond(CC)); Spaces(8-Printed) Show Hex(N&16_00FF FFFF, 6) ->Done %finish %unless N>>8&15 = 1 %start Print string("EQUD "); Show Hex(N,8) -> Done %finish {this leaves the floating point stuff} %if N&16_0000 0010 = 0 %start {CPDO} X = (N>>19)&2_11110 ! (N>>15)&1 ->Fm(X) Fm(2_00000): Put("ADF"); ->FnOP Fm(2_00010): Put("MUF"); ->FnOP Fm(2_00100): Put("SUF"); ->FnOP Fm(2_00110): Put("RSF"); ->FnOP Fm(2_01000): Put("DVF"); ->FnOP Fm(2_01010): Put("RDF"); ->FnOP Fm(2_01100): Put("POW"); ->FnOP Fm(2_01110): Put("RPW"); ->FnOP Fm(2_10000): Put("RMF"); ->FnOP Fm(2_10010): Put("FML"); ->FnOP Fm(2_10100): Put("FDV"); ->FnOP Fm(2_10110): Put("FRD"); ->FnOP Fm(2_11000): Put("POL"); ->FnOP FnOP: Put(Cond(CC)) %if N&16_0008 0000 = 0 %start %if N&16_0000 0080 = 0 %then Put("S") %else Put("D") %finish %else %start %if N&16_0000 0080 = 0 %then Put("E") %else Put("?") %finish X = N>>5&3 %if X # 0 %start %if X = 2_01 %then Put("P") %else %C %if X = 2_10 %then Put("M") %else Put("Z") %finish Spaces(8-Printed) F Register(N>>12&7) Printstring(", ") F Register(N>>16&7) Op Rest: Printstring(", ") Show ConstReg(N&15) ->Done Fm(2_00001): Put("MVF"); ->FnOP1 Fm(2_00011): Put("MNF"); ->FnOP1 Fm(2_00101): Put("ABS"); ->FnOP1 Fm(2_00111): Put("RND"); ->FnOP1 Fm(2_01001): Put("SQT"); ->FnOP1 Fm(2_01011): Put("LOG"); ->FnOP1 Fm(2_01101): Put("LGN"); ->FnOP1 Fm(2_01111): Put("EXP"); ->FnOP1 Fm(2_10001): Put("SIN"); ->FnOP1 Fm(2_10011): Put("COS"); ->FnOP1 Fm(2_10101): Put("TAN"); ->FnOP1 Fm(2_10111): Put("ASN"); ->FnOP1 Fm(2_11001): Put("ACS"); ->FnOP1 Fm(2_11011): Put("ATN"); ->FnOP1 Fm(*): Put("???") FnOP1: Put(Cond(CC)) %if N&16_0008 0000 = 0 %start %if N&16_0000 0080 = 0 %then Put("S") %else Put("D") %finish %else %start %if N&16_0000 0080 = 0 %then Put("E") %else Put("?") %finish X = N>>5&3 %if X # 0 %start %if X = 2_01 %then Put("P") %else %C %if X = 2_10 %then Put("M") %else Put("Z") %finish Spaces(8-Printed) F Register(N>>12&7) ->Op Rest %finish %else %if N&16_0010F000 = 16_0010F000 {CPST} %start X = N>>21&7 %if X = 2_100 %start Put("CMF") %finish %else %if X = 2_101 %start Put("CNF") %finish %else %if X = 2_110 %start Put("CMFE") %finish %else %if X = 2_111 %start Put("CNFE") %finish %else %start Put("???") %finish Put(Cond(CC)) Spaces(8-Printed) F Register(N>>16&7) ->Op Rest %finish %else %start {CPRT} X = N>>20&15 %if X = 0 %start Put("FLT") %finish %else %if X = 1 %start Put("FIX") %finish %else %if X = 2 %start Put("WFS") %finish %else %if X = 3 %start Put("RFS") %finish %else %if X = 4 %start Put("WFC") %finish %else %if X = 5 %start Put("RFC") %finish %else %start Put("???") %finish Put(Cond(CC)) %if N&16_0008 0000 = 0 %start %if N&16_0000 0080 = 0 %then Put("S") %else Put("D") %finish %else %start %if N&16_0000 0080 = 0 %then Put("E") %else Put("?") %finish Y = N>>5&3 %if Y # 0 %start %if Y = 2_01 %then Put("P") %else %C %if Y = 2_10 %then Put("M") %else Put("Z") %finish Spaces(8-Printed) %if X = 0 %start {FLT} F Register(N>>16&7) Printstring(", ") Register(N>>12&15) %finish %else %if X = 1 {FIX} %start Register(N>>12&15) Printstring(", ") Show Constreg(N&15) %finish %else %start Register(N>>12&15) %finish %finish Done: %result = Result string %end !########################################################################### %const %integer Data = 0, Instr = 1, B = 2, BL = 4, Swi = 8 %integerfn Get Simple Type(%integer Pc, N, %integer %name Dest, Access) %const %integer Always = 14, AddOp=4, MovOp = 1, pcreg = 15 %integer CC, Type, Op, Rn, Rd, Rs, Shf, Shift, Imm, Offset, Operand %integer X, Y, Z %switch F(0:7), Fm(0:31) Access = Avail CC = N>>28 Type = N>>25&7 Rd = (N>>12)&15 Rn = (N>>16)&15 ->F(Type) F(2_000): F(2_001): !%begin Op = (N>>21)&15 %if (Op=AddOp %or Op=MovOp) %and Rd=pc reg %and cc=always %start Access = blocked %finish %if op#13 %and op#15 %and %c Rd=pc reg %and Rn#pc reg %and cc=always %then access=blocked %if N&16_0200 0000 = 0 %start Shift = (N>>4)&255 Rs = Shift >> 4 %result=Data %if Rs=pc reg %and Shift&1 # 0 %finish %result = Instr !%end F(2_010): F(2_011): !%begin %result=Instr !%end F(2_100): !%begin %if N&16_0000 ffff = 0 %then %result=Data ;! LDM Rn!,{} for instance %if N&16_0010 0000 = 0 %then %result=Instr %if N&(1<<15)#0 %and cc=always %then Access=blocked %result = Instr !%end F(2_101): !%begin Type = B; Type = BL %if N&16_0100 0000 # 0 X = N&16_00FF FFFF X = X!16_FF00 0000 %if X&16_0080 0000 # 0 Dest = Pc+(2+X)*4 %if type=B %and CC=Always %then Access=Blocked %result = Type !%end F(2_110): !%begin %result = Instr !%end F(2_111): !%begin %if N&16_0100 0000 # 0 %start Dest = N&16_00FF FFFF %result = SWI %finish %result = Data %if N>>8&15 # 1 {this leaves the floating point stuff} %if N&16_0000 0010 = 0 %start {CPDO} -> Fm((N>>19)&2_11110 ! (N>>15)&1) Fm(2_00000): Fm(2_00010): Fm(2_00100): Fm(2_00110): Fm(2_01000): Fm(2_01010): Fm(2_01100): Fm(2_01110): Fm(2_10000): Fm(2_10010): Fm(2_10100): Fm(2_10110): Fm(2_11000): Fm(2_00001): Fm(2_00011): Fm(2_00101): Fm(2_00111): Fm(2_01001): Fm(2_01011): Fm(2_01101): Fm(2_01111): Fm(2_10001): Fm(2_10011): Fm(2_10101): Fm(2_10111): Fm(2_11001): Fm(2_11011): %if N&16_0008 0000 # 0 %and %c N&16_0000 0080 # 0 %then %result=Data %result = Instr Fm(*): %result=Data %finish %else %if N&16_0010F000 = 16_0010F000 {CPST} %start X = N>>21&7 %result = Data %unless 2_100 <= X <= 2_111 %result = Instr %finish %else %start {CPRT} X = N>>20&15 %result = Data %unless 0 <= X <= 5 %if N&16_0008 0000 # 0 %and %c N&16_0000 0080 # 0 %then %result = Data %result = Instr %finish !%end %end !########################################################################### %integerfn Valid Instr(%integer PC) %integer Type, Dest, Access Type = Get Simple type(PC, INTEGER(PC), Dest, Access) %if Type#Data %then %result=TRUE %else %result=FALSE %end %routine Decode(%integer from, to, start, end) %byte %array tag(from:to) %routine Text(%string(255) S) print string(S) newline %end %string(4) %fn sanitised(%integer is) %string (4) s; s = "" %integer i i = (is)&255 i = '.' %unless ' '<=i<='~'; s = s.tostring(i) i = (is >> 8)&255 i = '.' %unless ' '<=i<='~'; s = s.tostring(i) i = (is >> 16)&255 i = '.' %unless ' '<=i<='~'; s = s.tostring(i) i = (is >> 24)&255 i = '.' %unless ' '<=i<='~'; s = s.tostring(i) %result=s %end %routine Print Decode(%integer from, to) %integerfn pr(%integer a) %result=TRUE %if ' '<=BYTEINTEGER(a)<='~' %result=FALSE %end %string(255) %fn CharStr(%integer a) %string(255) guts %if tag(a)&Def char#0 %and pr(a)=TRUE %start guts = """".tostring(BYTEINTEGER(a))."""" %finish %else %start guts = itos(BYTEINTEGER(a), 0) guts = " ".guts %while LENGTH(guts)<3 %finish %result = guts %end %string(10) Lab %string(255) Guts %const %integer max guts = 50 %integer a, type, dest, access; a = from %cycle %if tag(a)&Def labelled#0 %start %if tag(a)&Def Call Dest#0 %then %start Lab = "P" %finish %else %if tag(a)&Def Branch Dest#0 %then %start Lab = "L" %finish %else %start Lab = "D" %finish Lab = Lab.Itoh(a, 8)." " %finish %else %start Lab = " " %finish %if tag(a)&Def Inst#0 %start guts = Instr decode(a, INTEGER(a)) Type = Get Simple type(a, INTEGER(a), Dest, Access) %if Type&(B!BL)#0 %start %unless from <= dest <= to %start guts = guts." ; Outside module???" %finish %finish guts <- guts." " %finish %else %if tag(a)&Def Word#0 %start guts = "EQUD &".itoh(INTEGER(a),8)." ". %C " " %finish %else %if tag(a)&(Def Byte!Def Char)#0 %start guts = "= " %if pr(a)=TRUE %and pr(a+1)=TRUE %and pr(a+2)=TRUE %and pr(a+3)=TRUE %start guts = "= """.tostring(BYTEINTEGER(a)).tostring(BYTEINTEGER(a+1)).tostring(BYTEINTEGER(a+2)).tostring(BYTEINTEGER(a+3))."""" %finish %else %start guts = guts.CharStr(a).", " guts = guts.CharStr(a+1).", " guts = guts.CharStr(a+2).", " guts = guts.CharStr(a+3) %finish guts = guts." " LENGTH(guts) = 20 %finish %else %start ! Unknown - could be data or instr... %if Valid Instr(a)=TRUE %start guts = Instr decode(a, INTEGER(a)) guts <- guts." " %finish %else %start guts = "EQUD &".itoh(INTEGER(a),8)." ". %C " " %finish LENGTH(guts) = Max guts-6 guts = guts."; ".sanitised(INTEGER(a)) %finish LENGTH(guts) = max guts text(Lab.guts."; ".itoh(a,7).": ".itoh(INTEGER(a),8)) a = a+4 %return %if a >= to %repeat %end %string(255) %fn StringAt(%integer Str addr) %string (255) Title Title = "" %cycle %if BYTEINTEGER(Str addr)=0 %then %result=Title Title = Title.tostring(BYTEINTEGER(Str addr)) Str addr = Str addr+1 %repeat %end %routine Mark string(%integer str start) %return %if BYTEINTEGER(str start)=0 tag(str start) = tag(str start)!Def labelled %cycle tag(str start) = tag(str start)!Def Char %if BYTEINTEGER(str start) = 0 %then tag(Str start)=tag(Str start)! %c Def byte %and %return str start=str start+1 %repeat %end %routine Mark word(%integer ad) tag(ad) = tag(ad)!Def word tag(ad+1) = Def word tag(ad+2) = Def word tag(ad+3) = Def word %end %routine Mark Byte(%integer ad) tag(ad) = tag(ad)!Def Byte %end %routine Mark Jump(%integer ad) tag(ad) = tag(ad)!Def Inst!Def Labelled!Def Branch dest %end %routine Mark Proc(%integer ad) tag(ad) = tag(ad)!Def Inst!Def Labelled!Def Call dest %end %routine %spec Decode Branch Search(%integer Entry, From, To) %routine %spec Decode Proc Search(%integer Entry, From, To) %routine Decode Search(%integer Entry, from, to) %integer Type, Dest, Access; Access = avail %return %unless From <= Entry < To %and Entry&3=0 %return %if tag(Entry)&Def Inst#0 {Already searched} %cycle %exit %if tag(Entry)&(Def Char!Def Byte!Def Inst)#0 %or Entry >= To Type = Get Simple type(Entry, INTEGER(Entry), Dest, Access) %if Type=Data %then %start ! Somehow missed end of instr seq. ! Backtrack and undo? %return %finish tag(Entry) = tag(Entry)!Def Inst %if Type&B # 0 %start %unless from <= dest < To %start !!! tag(Entry) = tag(Entry)&(\Def Inst) !!! %return %finish Decode Branch Search(dest, from, to) tag(entry)=tag(Entry)!Def access %and %return %if Access=blocked Entry = Entry+4 %finish %else %if Type&BL # 0 %start %unless from <= dest < To %start !! tag(Entry) = tag(Entry)&(\Def Inst) !! %return %finish Decode Proc Search(dest, from, to) Entry = Entry+4 %finish %else %if Type&SWI # 0 %start %if Dest&(\16_20000)=1 %start ! Skip in-line string tag(Entry)=tag(Entry)!Def access Entry=Entry+4 Mark String(Entry) %while BYTEINTEGER(Entry)#0 %cycle Entry = Entry+1 %repeat Entry = (Entry+4)&(\3) %finish %else %start Entry = Entry + 4 %finish %finish %else %start tag(entry)=tag(Entry)!Def access %and %return %if Access=blocked Entry = Entry+4 %finish %repeat %end %routine Decode Branch Search(%integer Entry, From, To) %return %unless From <= Entry <= To %and Entry&3=0 tag(Entry) = tag(Entry)!Def labelled!Def branch dest Decode Search(Entry, From, To) %end %routine Decode Proc Search(%integer Entry, From, To) %return %unless From <= Entry <= To %and Entry&3=0 tag(Entry) = tag(Entry)!Def labelled!Def call dest Decode Search(Entry, From, To) %end %integerfn Decode Title String(%integer Str addr, %string(*) %name Title) Title = "" %cycle %if BYTEINTEGER(Str addr)=0 %then %result=TRUE %unless '!' <= BYTEINTEGER(Str addr) <= '~' %then %result=FALSE Title = Title.tostring(BYTEINTEGER(Str addr)) Str addr = Str addr+1 %repeat %end %integerfn Decode Help String(%integer Str addr, %integer %name Help length) Help length = 0 %cycle %if BYTEINTEGER(Str addr) = 0 %then %result=TRUE %if BYTEINTEGER(Str addr) >= 127 %then %result=FALSE str addr = Str addr+1; Help length = Help length+1 %repeat %end %routine Decode Help Table(%integer Start) %record %format Help info fm(%integer code, %byte min params, flags0, max params, flags 1, %integer syntax, text) %string(255) %fn Params(%integer Low, High) %result = "" %if low=High=0 %result = " (".itos(High,0)." param)" %if low=high=1 %result = " (".itos(High,0)." params)" %if low=high %result = " (".itos(low,0)."-".itos(high,0)." params)" %end %record (Help info fm) %name Help info %string (255) Help param %cycle Help param = StringAt(Start) Mark string(start) %return %if Help param = "" Start = (Start + LENGTH(Help param) + 1 + 3) & (\3) Help info == RECORD(Start) Mark Word(start) Mark Byte(start+4); Mark Byte(start+5) Mark Byte(start+6); Mark Byte(start+7) Mark word(start+8); Mark word(start+12) %if Help info_code = 0 %start Text("Help on: ".help param. %C Params(Help info_min params, Help info_max params)) %finish %else %start Decode proc search(from+Help info_code, from, to) Text("Entry: ".help param. %C Params(Help info_min params, Help info_max params)) %finish Mark string(from+Help info_syntax) Mark string(from+Help info_text) start = start+16 %repeat %end %routine Decode SWI Table(%integer Start) %cycle %cycle %exit %if BYTEINTEGER(Start)=0 tag(Start)=Def char Start=Start+1 %repeat tag(Start)=tag(start)!Def char Start=Start+1 %repeat %until BYTEINTEGER(start)=0 tag(start)=tag(start)!Def char %end %routine Scan branches(%integer from, to) %integer address, Type, Dest, Access %for address = From, 4, To-4 %cycle %if tag(address)!tag(address+1)!tag(address+2)!tag(address+3)=0 %start Type = Get Simple type(address, INTEGER(address), Dest, Access) %if Type&(B!BL)#0 %start %if from < dest <= to %and Access=Blocked %start tag(address)=tag(address)!Def Inst Decode branch search(Dest, from, to) %finish %else %start ! Leave undecided... tag(address)=tag(address)!Def word %finish %finish %finish %repeat %end %integerfn stringch(%integer i) i = BYTEINTEGER(i) %result=TRUE %if i=0 %or i=10 %or i=13 %or ' '<=i<='~' %result=FALSE %end %routine Scan strings(%integer from, to) %integer a, Type, Dest, Access %for a = From, 4, To-4 %cycle %if tag(a)!tag(a+1)!tag(a+2)!tag(a+3)=0 %start %if stringch(a-4)=TRUE %and stringch(a-3)=TRUE %c %and stringch(a-2)=TRUE %and stringch(a-1)=TRUE %c %and stringch(a)=TRUE %and stringch(a+1)=TRUE %c %and stringch(a+2)=TRUE %and stringch(a+3)=TRUE %c %and stringch(a+4)=TRUE %and stringch(a+4)=TRUE %c %and stringch(a+6)=TRUE %and stringch(a+7)=TRUE %c %start %if INTEGER(a)=0 %then tag(a)=tag(a)!Def Word %else %start tag(a)=tag(a)!Def Char;tag(a+1)=tag(a+1)!def char tag(a+2)=tag(a+2)!Def Char;tag(a+3)=tag(a+3)!def Char %finish %if BYTEINTEGER(a+2)=BYTEINTEGER(a+3)=0 %then tag(a)=tag(a)!Def Word %finish %finish %repeat %end %routine Scan data(%integer from, to) %integer a %for a = From, 4, To-4 %cycle %if tag(a)!tag(a+1)!tag(a+2)!tag(a+3)=0 %start %if 16_ffff0000 <= INTEGER(a) <= 16_0000ffff %start tag(a) = Def Word %finish %finish %repeat %end %routine Confirm(%integer first, last, from, to) ! if all the words between first and last can take the ! same type as them, set them to that... %end %routine Patch up alternatives(%integer from, to) %integer a, start %for a = From, 4, To-4 %cycle %if tag(a)!tag(a+1)!tag(a+2)!tag(a+3)=0 %start start=a+4 %while tag(start)!tag(start+1)!tag(start+2)!tag(start+3)=0 %cycle start=start+4 %repeat Confirm(a-4, start, from, to) %finish %repeat %end %integerfn printable(%integer ad) %result=TRUE %if ' ' <= BYTEINTEGER(ad) <= '~' %result=FALSE %end %integerfn all printable(%integer ad) %if printable(ad)=TRUE %and printable(ad+1)=TRUE %c %and printable(ad+2)=TRUE %and printable(ad+3)=TRUE %then %result=TRUE %result=FALSE %end %routine Undo wrong instructions(%integer From, to) %integer Dest, Access, Type, a %for a = to-4, -4, from+4 %cycle %if tag(a)&Def Char#0 %and tag(a-4)=0 %start Type = Get Simple type(a-4, INTEGER(a-4), Dest, Access) %if Type&(Instr!BL)#0 %and access#blocked %start tag(a-4) = Def Char %finish %continue %finish %else %if tag(a)&def char#0 %and tag(a-4)&Def word#0 %start tag(a-4) = tag(a-4)&(\Def Word)!Def char %if all printable(a-4)=TRUE %finish %else %if tag(a)&Def Word#0 %and tag(a-4)=0 %start Type = Get Simple type(a-4, INTEGER(a-4), Dest, Access) %if Type&(Instr!BL!SWI)#0 %and access#blocked %start %if all printable(a-4)=TRUE %start tag(a-4) = Def Char %finish %else %start tag(a-4) = Def Word %finish %finish %continue %finish %if (tag(a)&Def Inst=0 %or (tag(a)=0 %and %not valid instr(a)=TRUE)) %c %and (tag(a-4)=0 %or %c (tag(a-4)&Def Inst#0 {%and Dubious branch})) %start ! if a-4 can drop through then it is not an instr... ! Give it DATA? Type = Get Simple type(a-4, INTEGER(a-4), Dest, Access) %if Type&Data=0 %c %and Access#blocked %and tag(a-4)&Def Labelled#0 %start tag(a)=Def Word %if tag(a)=0 tag(a-4)=tag(a-4)&(\Def Inst)!(tag(a)&(Def char!Def Word!Def Byte)) %finish %finish %repeat %end %routine Grab more strings(%integer from, to) %integer a %for a = from, 4, to-4 %cycle %if tag(a) & Def char # 0 %and tag(a+4) & Def word # 0 %start %if all printable(a+4)=TRUE %start tag(a+4) = tag(a+4) & (\def word) ! def char %finish %finish %repeat %end %routine Set any illegal instrs to DATA(%integer from, to) %integer a %for a = from, 4, to %cycle %if tag(a)=0 %and tag(a+1)=0 %and tag(a+2)=0 %and tag(a+3)=0 %start %if %not valid instr(a)=TRUE %then tag(a)=Def Word %finish %repeat %end %integer i tag(i) = 0 %for i = from, 1, to ! Determine type - module or file: Follow entry points as appropriate. %record %format Module Header Fm( %c %integer Start Code, Init Code, Final Code, Service Handler, Title String, Help String, Help table, SWI Chunk, SWI Handler, SWI Table, SWI Decode) %record (Module Header Fm) %name Module Header %integer Code extent; Code extent = to - from Module Header == RECORD(from) %if 0 <= Module Header_Init Code < Code extent %c %and 0 <= Module Header_Final Code < Code extent %c %and 0 <= Module Header_Service Handler < Code extent %c %and 0 <= Module Header_Title String < Code extent %c %and 0 <= Module Header_Help String < Code extent %c %and 0 <= Module Header_Help Table < Code extent %c %then %start %begin ! Good chance of it being a module. %string (255) Title %if Decode Title String(from+Module Header_Title String, Title)=TRUE %start Mark string(from+Module Header_title string) Text("*** Decoding relocatable module '".Title."' ***") %finish %else %start Text("*** This appears to be a module but the title string is invalid") %finish Mark Word(i) %for i = from, 4, from+16_18 %begin %integer Help Length %if Decode Help String(from+Module Header_Help String, Help Length)=TRUE %start Mark string(from+Module Header_Help String) ! Help text marked. Possibly also print here too... %finish %end %if Module Header_Help Table#0 %start Decode Help Table(from+Module Header_Help Table) ! Table entries marked appropriately; entry points recursively decoded %finish %if Module Header_SWI Handler < Code extent %start %if Module Header_SWI Handler#0 %c %and Module Header_SWI Handler&2_11111100 00000000 00000000 00000011=0 %c %then %start Mark Word(ADDR(Module Header_SWI Handler)) Decode Proc Search(from+Module header_SWI Handler, from, to) %finish ! Only list SWI no's if SWIs valid. %if Module Header_SWI Chunk&2_11111111 00000000 00000000 00011111=0 %c %then %start Mark Word(ADDR(Module Header_SWI Chunk)) Text("Module handles SWIs from ". %C itoh(Module Header_SWI Chunk,6)." to ". %C itoh(Module Header_SWI Chunk+64-1,6)) %finish %if Module Header_SWI Table < Code extent %start %if Module Header_SWI Table#0 %c %and Module Header_SWI Table&2_11111100 00000000 00000000 00000011=0 %c %then %start Mark Word(ADDR(Module Header_SWI Table)) Decode SWI Table(from+Module Header_SWI Table) %finish %if Module Header_SWI Decode < Code extent %start %if Module Header_SWI Decode#0 %c %and Module Header_SWI decode&2_11111100 00000000 00000000 00000011=0 %c %then %start Mark Word(ADDR(Module Header_SWI Decode)) Decode Proc Search(from+Module header_SWI Decode, from, to) %finish %finish;%finish;%finish ! do main entry last as it is special... %if 0 < Module Header_Start Code < Code extent %start Text("Entry point is offset.") Decode Proc Search(from+Module header_Start Code, from, to) %finish %else %if Module header_start code = 0 %start ! No language entry %finish %else %start %if Valid Instr(from)=TRUE %start Decode Proc Search(from, from, to) ! First word is an instruction, not an offset %finish %else %start Text("*** First word not valid instruction ***") %finish %finish Decode Proc Search(from+Module header_Init Code, from, to) %c %unless Module header_Init Code=0 Decode Proc Search(from+Module header_Final Code, from, to) %c %unless Module header_Final Code=0 Decode Proc Search(from+Module header_Service Handler, from, to) %c %unless Module header_Service Handler=0 %end %else ! Probably not a module - treat as a file Decode Proc Search(from, from, to) %finish Scan branches(From, to) Scan strings(From, to) Scan data(from, to) Undo wrong instructions(from, to) {Inst (not jump) followed by Data} Grab more strings(from, to) Set any illegal instrs to DATA(from, to) Undo wrong instructions(from, to) {Iterative process!} Patch up alternatives(from, to) {If DATA, data!inst, DATA then DATA} Undo wrong instructions(from, to) {Iterative process!} Print decode(start, end) %end ! Decode (Module/code start, Module/code end, decode start, decode end) ! decode(16_8000, 16_DA50, 16_8000, 16_DA50) %string(255) s; s = "MOS" {cli param} %if s = "MOS" %start decode(16_3800000, 16_380837C, 16_3800000, 16_380837C) %finish %else %if s = "NFS" %start decode(16_18B2A64, 16_18C9304, 16_18B2A64, 16_18C9304) %finish %else %if s = "UtilityModule" %start decode(16_3806428, 16_38195E8, 16_3806428, 16_38195E8) %finish %else %if s = "FileSwitch" %start decode(16_38195E8, 16_381EC34, 16_38195E8, 16_381EC34) %finish %else %if s = "BASIC" %start decode(16_381EC34, 16_382A5C4, 16_381EC34, 16_382A5C4) %finish %else %if s = "ADFS" %start decode(16_382A5C4, 16_38325A4, 16_382A5C4, 16_38325A4) %finish %else %if s = "Econet" %start decode(16_38325A4, 16_3834184, 16_38325A4, 16_3834184) %finish %else %if s = "NetFS" %start decode(16_3834184, 16_3837F60, 16_3834184, 16_3837F60) %finish %else %if s = "WindowManager" %start decode(16_3837F60, 16_383C558, 16_3837F60, 16_383C558) %finish %else %if s = "SpriteUtils" %start decode(16_383C558, 16_383CE30, 16_383C558, 16_383CE30) %finish %else %if s = "SoundDMA" %start decode(16_383CE30, 16_383D8A8, 16_383CE30, 16_383D8A8) %finish %else %if s = "SoundChannels" %start decode(16_383D8A8, 16_383ED58, 16_383D8A8, 16_383ED58) %finish %else %if s = "SoundScheduler" %start decode(16_383ED58, 16_383F588, 16_383ED58, 16_383F588) %else %if s # "" %and s#"-help" %then print string("Error: a") %else print string("A") print string(%c "llowed parameters are: NFS MOS UtilityModule FileSwitch ADFS Econet NetFS WindowManager SpriteUtils SoundDMA SoundChannels SoundScheduler ") %finish %endofprogram