Modules.Mos 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. (* ported version of Minos to work with the ARM backend of the Fox Compiler Suite *)
  2. MODULE Modules;
  3. (*@
  4. 001 2007-03-20 fn: New version based on old Modules Module, adapted to new compiler
  5. *)
  6. IMPORT SYSTEM, Kernel, Platform, OFS, Strings, Tools, Heaps, Caches, Log, Trace;
  7. CONST
  8. OK*= 0; NOTFOUND* = 1; NOTARM* = 2; WRONGKEY*=3; NOMEMORY* = 4;
  9. (* Linking *)
  10. MAXIMPS = 256;
  11. C16 = 10000H; C24 = 1000000H;
  12. TYPE Name = ARRAY 32 OF CHAR;
  13. Command* = POINTER TO CommandDesc;
  14. CommandDesc = RECORD
  15. next*: Command;
  16. offset: LONGINT;
  17. name*: Name
  18. END;
  19. EntryTable = POINTER TO EntryTableDesc;
  20. EntryTableDesc = RECORD
  21. entry: ARRAY 256 OF LONGINT
  22. END;
  23. Module* = POINTER TO ModuleDesc;
  24. ModuleDesc = RECORD
  25. next*: Module;
  26. key: LONGINT; (* Unique key of Module *)
  27. dbase, pbase*: LONGINT; (* dbase : Base address of Module Variables, pbase: Base address of code *)
  28. size*, refcnt*: LONGINT; (* size: code size in bytes, rofcnt: reference counter *)
  29. command*: Command; (* First command *)
  30. entrytable: EntryTable; (* Array containing the offset rel to pbase for each exported function *)
  31. name*: Name (* Name of module *)
  32. END;
  33. VAR root*: Module;
  34. res: LONGINT;
  35. errstring*: ARRAY 32 OF CHAR;
  36. PROCEDURE GetRes*(VAR err: ARRAY OF CHAR): LONGINT;
  37. BEGIN
  38. Strings.Copy(errstring, err);
  39. RETURN res
  40. END GetRes;
  41. PROCEDURE JoinExtension (CONST name, extension: ARRAY OF CHAR; VAR fullname: ARRAY OF CHAR);
  42. VAR i, j: LONGINT;
  43. BEGIN
  44. i := 0; WHILE name[i] # 0X DO fullname[i] := name[i]; INC(i) END;
  45. j := 0; WHILE extension[j] # 0X DO fullname[i] := extension[j]; INC(i); INC(j) END;
  46. fullname[i] := 0X
  47. END JoinExtension;
  48. PROCEDURE MakeName (CONST name: ARRAY OF CHAR; VAR fullname: ARRAY OF CHAR);
  49. BEGIN JoinExtension (name, ".arm", fullname)
  50. END MakeName;
  51. PROCEDURE ReadString (VAR r: OFS.Rider; VAR string: ARRAY OF CHAR);
  52. VAR ch: CHAR; i: LONGINT;
  53. BEGIN i := 0;
  54. REPEAT OFS.Read (r, ch); string[i] := ch; INC (i) UNTIL ch = 0X;
  55. END ReadString;
  56. PROCEDURE Fixup(pbase, fixloc, offset, base: LONGINT; CONST entry: ARRAY OF LONGINT);
  57. VAR instr, next, pno, vno, reg, disp: LONGINT;
  58. BEGIN
  59. (*
  60. Trace.Ln;
  61. Trace.String("Fixup : pbase : "); Trace.Hex( pbase, -8 ); Trace.String(", fixloc : "); Trace.Hex( fixloc, -8 ); Trace.String(", offset : "); Trace.Hex( offset, -8 ); Trace.String(", base : "); Trace.Hex( base, -8 ); Trace.Ln;
  62. *)
  63. WHILE fixloc # 0 DO
  64. SYSTEM.GET (pbase + fixloc*4, instr); next := instr MOD LONGINT( 10000H );
  65. (* Trace.String("GET("); Trace.Hex( pbase+fixloc*4, -8 ); Trace.String("), Inst : "); Trace.Hex( instr, -8 ); Trace.String(", next "); Trace.Hex( next, -8 ); Trace.Ln; *)
  66. pno := instr DIV LONGINT( 10000H ) MOD LONGINT( 100H );
  67. IF instr DIV LONGINT( 1000000H ) MOD LONGINT( 100H ) = LONGINT( 0EBH ) THEN (* case BL *)
  68. instr := instr DIV LONGINT( 1000000H ) * LONGINT( 1000000H ) + LONGINT(entry[pno] + offset - fixloc - 2) MOD LONGINT( 1000000H );
  69. (*ELSIF instr DIV 1000000H = 0 THEN (*indir. variable address*) instr := entry[pno] + base*)
  70. ELSE (*indir. proc. address*) instr := LONGINT( entry[pno]*4 ) + base
  71. END ;
  72. (* Trace.String("PUT : "); Trace.Hex( instr, -8 ); Trace.String(", next : "); Trace.Hex( next*4+pbase, -8 ); Trace.Ln; *)
  73. SYSTEM.PUT (pbase + fixloc*4, instr); fixloc := next
  74. END
  75. END Fixup;
  76. PROCEDURE FixSelf (pbase, fixloc, base: LONGINT);
  77. VAR instr, next: LONGINT;
  78. BEGIN
  79. (*
  80. Trace.Ln;
  81. Trace.String("FixSelf : pbase : "); Trace.Hex( pbase, -8 ); Trace.String(", fixloc : "); Trace.Hex( fixloc, -8 ); Trace.String(", base : "); Trace.Hex( base, -8 ); Trace.Ln;
  82. *)
  83. WHILE fixloc # 0 DO
  84. SYSTEM.GET (pbase+fixloc*4, instr); next := instr MOD 10000H;
  85. (* Trace.String("GET("); Trace.Hex( pbase+fixloc*4, -8 ); Trace.String("), Inst : "); Trace.Hex( instr, -8 ); Trace.String(", next "); Trace.Hex( next, -8 ); Trace.Ln; *)
  86. SYSTEM.PUT (pbase+fixloc*4, instr DIV 10000H * 4 + base);
  87. (* Trace.String("PUT("); Trace.Hex( pbase+fixloc*4, -8 ); Trace.String(", inst "); Trace.Hex( instr DIV 10000H *4 + base, -8 ); Trace.Ln; *)
  88. fixloc := next;
  89. END
  90. END FixSelf;
  91. PROCEDURE FindModule*(CONST name: ARRAY OF CHAR; VAR m: Module);
  92. BEGIN m := root;
  93. WHILE (m # NIL) & ~Strings.EqualIgnoreCase(m.name, name) DO m := m.next END;
  94. END FindModule;
  95. PROCEDURE Call (m: Module; entry: LONGINT);
  96. VAR
  97. p: PROCEDURE;
  98. BEGIN
  99. SYSTEM.PUT ( ADDRESSOF( p ), m.pbase + entry * 4); p
  100. END Call;
  101. PROCEDURE CallP*(m: Module; CONST pname: ARRAY OF CHAR): BOOLEAN;
  102. VAR cmd: Command;
  103. BEGIN cmd := m.command;
  104. WHILE (cmd # NIL) & (cmd.name # pname) DO cmd := cmd.next END;
  105. IF cmd # NIL THEN Call (m, cmd.offset) END;
  106. RETURN cmd # NIL
  107. END CallP;
  108. PROCEDURE PrintModuleInfo*( m: Module );
  109. VAR
  110. c : Command;
  111. i : LONGINT;
  112. doLoop : BOOLEAN;
  113. BEGIN
  114. IF m # NIL THEN
  115. Trace.String("Module: "); Trace.StringLn(m.name);
  116. Trace.String("size "); Trace.Int( m.size, 3 ); Trace.Ln;
  117. Trace.String("dbase: "); Trace.Hex( m.dbase, -8 ); Trace.Ln;
  118. Trace.String("pbase: "); Trace.Hex( m.pbase, -8 ); Trace.Ln;
  119. Trace.Memory( m.pbase, m.size );
  120. Trace.StringLn("Commands:");
  121. c := m.command;
  122. WHILE ( c # NIL ) DO
  123. Trace.String( c.name ); Trace.String(", "); Trace.Hex( c.offset, -8 ); Trace.String(", abs "); Trace.Hex( m.pbase+c.offset, -8 ); Trace.Ln;
  124. c := c.next;
  125. END;
  126. Trace.Ln;
  127. Trace.StringLn("Entry Table : ");
  128. i := 0; doLoop :=TRUE;
  129. WHILE ( i < 256 ) & ( doLoop ) DO
  130. IF ( i > 3 ) THEN
  131. IF ( m.entrytable.entry[ i ] = 0 ) THEN
  132. doLoop := FALSE;
  133. END;
  134. END;
  135. Trace.Int( i , 3 ); Trace.String(": "); Trace.Hex( m.entrytable.entry[ i ], -8 ); Trace.String(", abs : "); Trace.Hex( m.entrytable.entry[ i ]+m.pbase, -8 ); Trace.Ln;
  136. INC( i );
  137. END;
  138. Trace.Ln;
  139. END;
  140. END PrintModuleInfo;
  141. (* Remove a module from the free module list *)
  142. (* PROCEDURE RemoveMod(mod: Module);
  143. VAR
  144. m, prevMod: Module;
  145. BEGIN
  146. m := mod;
  147. IF m = root THEN
  148. root := root.next;
  149. ELSE
  150. REPEAT
  151. prevMod := m;
  152. m := m.next;
  153. UNTIL (m = NIL) OR (m = mod);
  154. IF m = mod THEN prevMod.next := m.next; END;
  155. END;
  156. END RemoveMod;
  157. *)
  158. PROCEDURE ThisMod* (CONST modname: ARRAY OF CHAR; VAR mod: Module);
  159. VAR imp: Module; cmd: Command;
  160. nofimp, nofentries, codelen, fix, fixself, i, j, base: LONGINT;
  161. f: OFS.File; r: OFS.Rider; err: BOOLEAN;
  162. name: ARRAY 32 OF CHAR;
  163. key, offset, datasize: LONGINT;
  164. import: ARRAY MAXIMPS OF Module;
  165. fixroot: ARRAY MAXIMPS OF LONGINT;
  166. tempMod: Module;
  167. BEGIN
  168. mod := root; res := OK;
  169. WHILE (mod # NIL) & (mod.name # modname) DO mod := mod.next; END;
  170. IF mod = NIL THEN (*load*)
  171. MakeName (modname, name);
  172. f := OFS.Old(name);
  173. IF f = NIL THEN f:= Tools.RemoteReadFile(name); END;
  174. IF f = NIL THEN
  175. mod:=NIL; res := NOTFOUND; Strings.Copy (name, errstring);
  176. ELSE
  177. OFS.Set(r, f, 0);
  178. NEW(mod); mod.next := root; mod.refcnt := 0; root := mod;
  179. ReadString (r, mod.name);
  180. OFS.ReadInt (r, mod.key);
  181. OFS.ReadInt (r, fixself);
  182. ReadString (r, name); err := FALSE; i := 0;
  183. Trace.String("Load "); Trace.String( name ); Trace.StringLn(", done.");
  184. WHILE (name[0] # 0X) & (res = OK) DO
  185. OFS.ReadInt (r, key); OFS.ReadInt (r, fix);
  186. ThisMod (name, imp);
  187. IF imp # NIL THEN
  188. IF key = imp.key THEN
  189. import[i] := imp; INC (imp.refcnt); fixroot[i] := fix; INC(i)
  190. ELSE
  191. res := WRONGKEY; Strings.Copy (name, errstring); (* RemoveMod(mod); *) mod := NIL;
  192. END
  193. END;
  194. ReadString (r, name);
  195. END;
  196. nofimp := i;
  197. Trace.StringLn("Imports Done.");
  198. IF res = OK THEN
  199. i := 0;
  200. mod.command := NIL;
  201. ReadString (r, name);
  202. WHILE name[0] # 0X DO
  203. NEW (cmd); cmd.next := mod.command; mod.command := cmd;
  204. OFS.ReadInt (r, cmd.offset); cmd.name := name;
  205. ReadString (r, name);
  206. END;
  207. OFS.ReadInt (r, nofentries); NEW (mod.entrytable);
  208. FOR i:=0 TO 255 DO
  209. mod.entrytable.entry[0] := 0;
  210. END;
  211. OFS.ReadInt (r, mod.entrytable.entry[0]);
  212. i := 0;
  213. WHILE i < nofentries DO
  214. INC(i);
  215. OFS.ReadInt(r, mod.entrytable.entry[i]);
  216. END ;
  217. Trace.StringLn("Entry Table done.");
  218. OFS.ReadInt (r, datasize);
  219. Heaps.Alloc(mod.dbase, datasize);
  220. base := mod.dbase; WHILE datasize # 0 DO SYSTEM.PUT (base, 0); DEC (datasize, 4); INC (base, 4) END;
  221. OFS.ReadInt (r, codelen); mod.size := codelen * 4;
  222. Trace.StringLn("Data Section done.");
  223. Heaps.Alloc(mod.pbase, mod.size);
  224. base := mod.pbase; WHILE codelen # 0 DO OFS.ReadInt (r, i); SYSTEM.PUT (base, i); DEC (codelen); INC (base, 4) END;
  225. FixSelf(mod.pbase, fixself, mod.pbase); i := 0;
  226. WHILE i < nofimp DO
  227. offset := import[i].pbase - mod.pbase;
  228. Fixup(mod.pbase, fixroot[i], (import[i].pbase - mod.pbase) DIV 4, import[i].pbase, import[i].entrytable.entry); INC(i);
  229. END;
  230. Trace.StringLn("Code Section done.");
  231. (*
  232. FOR i := 0 TO mod.size-1 BY 4 DO
  233. SYSTEM.GET(mod.pbase+i*4, j);
  234. END;
  235. *)
  236. (* make sure all the data is flushed before we try and call the program *)
  237. Caches.CleanDCacheRange( mod.pbase, mod.size );
  238. Trace.StringLn("Cache flushed.");
  239. Call ( mod, mod.entrytable.entry[0] );
  240. Trace.StringLn("Call done.");
  241. ELSE
  242. (* Failed to load module, therefore remove it from the list of loaded modules *)
  243. (* RemoveMod(mod); *)
  244. END;
  245. OFS.Close (f);
  246. END;
  247. END;
  248. END ThisMod;
  249. BEGIN
  250. SYSTEM.GET ( Platform.ModRoot, root );
  251. END Modules.