Modules.Mos 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  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, Heaps, Caches, 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. pno := instr DIV LONGINT( 10000H ) MOD LONGINT( 100H );
  66. IF instr DIV LONGINT( 1000000H ) MOD LONGINT( 100H ) = LONGINT( 0EBH ) THEN (* case BL *)
  67. instr := instr DIV LONGINT( 1000000H ) * LONGINT( 1000000H ) + LONGINT(entry[pno] + offset - fixloc - 2) MOD LONGINT( 1000000H );
  68. (*ELSIF instr DIV 1000000H = 0 THEN (*indir. variable address*) instr := entry[pno] + base*)
  69. ELSE (*indir. proc. address*) instr := LONGINT( entry[pno]*4 ) + base
  70. END ;
  71. SYSTEM.PUT (pbase + fixloc*4, instr); fixloc := next
  72. END
  73. END Fixup;
  74. PROCEDURE FixSelf (pbase, fixloc, base: LONGINT);
  75. VAR instr, next: LONGINT;
  76. BEGIN
  77. (*
  78. Trace.Ln;
  79. Trace.String("FixSelf : pbase : "); Trace.Hex( pbase, -8 ); Trace.String(", fixloc : "); Trace.Hex( fixloc, -8 ); Trace.String(", base : "); Trace.Hex( base, -8 ); Trace.Ln;
  80. *)
  81. WHILE fixloc # 0 DO
  82. SYSTEM.GET (pbase+fixloc*4, instr); next := instr MOD 10000H;
  83. SYSTEM.PUT (pbase+fixloc*4, instr DIV 10000H * 4 + base);
  84. fixloc := next;
  85. END
  86. END FixSelf;
  87. PROCEDURE FindModule*(CONST name: ARRAY OF CHAR; VAR m: Module);
  88. BEGIN m := root;
  89. WHILE (m # NIL) & ~Strings.EqualIgnoreCase(m.name, name) DO m := m.next END;
  90. END FindModule;
  91. PROCEDURE Call (m: Module; entry: LONGINT);
  92. VAR
  93. p: PROCEDURE;
  94. BEGIN
  95. SYSTEM.PUT ( ADDRESSOF( p ), m.pbase + entry * 4); p
  96. END Call;
  97. PROCEDURE CallP*(m: Module; CONST pname: ARRAY OF CHAR): BOOLEAN;
  98. VAR cmd: Command;
  99. BEGIN cmd := m.command;
  100. WHILE (cmd # NIL) & (cmd.name # pname) DO cmd := cmd.next END;
  101. IF cmd # NIL THEN Call (m, cmd.offset) END;
  102. RETURN cmd # NIL
  103. END CallP;
  104. PROCEDURE PrintModuleInfo*( m: Module );
  105. VAR
  106. c : Command;
  107. i : LONGINT;
  108. doLoop : BOOLEAN;
  109. BEGIN
  110. IF m # NIL THEN
  111. (*Trace.String("Module: "); Trace.StringLn(m.name);
  112. Trace.String("size "); Trace.Int( m.size, 3 ); Trace.Ln;
  113. Trace.String("dbase: "); Trace.Hex( m.dbase, -8 ); Trace.Ln;
  114. Trace.String("pbase: "); Trace.Hex( m.pbase, -8 ); Trace.Ln;
  115. Trace.Memory( m.pbase, m.size );
  116. Trace.StringLn("Commands:");*)
  117. c := m.command;
  118. WHILE ( c # NIL ) DO
  119. (*Trace.String( c.name ); Trace.String(", "); Trace.Hex( c.offset, -8 ); Trace.String(", abs "); Trace.Hex( m.pbase+c.offset, -8 ); Trace.Ln;*)
  120. c := c.next;
  121. END;
  122. (*Trace.Ln;
  123. Trace.StringLn("Entry Table : ");*)
  124. i := 0; doLoop :=TRUE;
  125. WHILE ( i < 256 ) & ( doLoop ) DO
  126. IF ( i > 3 ) THEN
  127. IF ( m.entrytable.entry[ i ] = 0 ) THEN
  128. doLoop := FALSE;
  129. END;
  130. END;
  131. (*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;*)
  132. INC( i );
  133. END;
  134. (*Trace.Ln;*)
  135. END;
  136. END PrintModuleInfo;
  137. (* Remove a module from the free module list *)
  138. (* PROCEDURE RemoveMod(mod: Module);
  139. VAR
  140. m, prevMod: Module;
  141. BEGIN
  142. m := mod;
  143. IF m = root THEN
  144. root := root.next;
  145. ELSE
  146. REPEAT
  147. prevMod := m;
  148. m := m.next;
  149. UNTIL (m = NIL) OR (m = mod);
  150. IF m = mod THEN prevMod.next := m.next; END;
  151. END;
  152. END RemoveMod;
  153. *)
  154. PROCEDURE ThisMod* (CONST modname: ARRAY OF CHAR; VAR mod: Module);
  155. VAR imp: Module; cmd: Command;
  156. nofimp, nofentries, codelen, fix, fixself, i, j, base: LONGINT;
  157. f: OFS.File; r: OFS.Rider; err: BOOLEAN;
  158. name: ARRAY 32 OF CHAR;
  159. key, offset, datasize: LONGINT;
  160. import: ARRAY MAXIMPS OF Module;
  161. fixroot: ARRAY MAXIMPS OF LONGINT;
  162. tempMod: Module;
  163. BEGIN
  164. mod := root; res := OK;
  165. WHILE (mod # NIL) & (mod.name # modname) DO mod := mod.next; END;
  166. IF mod = NIL THEN (*load*)
  167. MakeName (modname, name);
  168. f := OFS.Old(name);
  169. IF f = NIL THEN
  170. mod:=NIL; res := NOTFOUND; Strings.Copy (name, errstring);
  171. ELSE
  172. OFS.Set(r, f, 0);
  173. NEW(mod); mod.next := root; mod.refcnt := 0; root := mod;
  174. ReadString (r, mod.name);
  175. OFS.ReadInt (r, mod.key);
  176. OFS.ReadInt (r, fixself);
  177. ReadString (r, name); err := FALSE; i := 0;
  178. (*Trace.String("Load "); Trace.String( name ); Trace.StringLn(", done.");*)
  179. WHILE (name[0] # 0X) & (res = OK) DO
  180. OFS.ReadInt (r, key); OFS.ReadInt (r, fix);
  181. ThisMod (name, imp);
  182. IF imp # NIL THEN
  183. IF key = imp.key THEN
  184. import[i] := imp; INC (imp.refcnt); fixroot[i] := fix; INC(i)
  185. ELSE
  186. res := WRONGKEY; Strings.Copy (name, errstring); (* RemoveMod(mod); *) mod := NIL;
  187. END
  188. END;
  189. ReadString (r, name);
  190. END;
  191. nofimp := i;
  192. (*Trace.StringLn("Imports Done.");*)
  193. IF res = OK THEN
  194. i := 0;
  195. mod.command := NIL;
  196. ReadString (r, name);
  197. WHILE name[0] # 0X DO
  198. NEW (cmd); cmd.next := mod.command; mod.command := cmd;
  199. OFS.ReadInt (r, cmd.offset); cmd.name := name;
  200. ReadString (r, name);
  201. END;
  202. OFS.ReadInt (r, nofentries); NEW (mod.entrytable);
  203. FOR i:=0 TO 255 DO
  204. mod.entrytable.entry[0] := 0;
  205. END;
  206. OFS.ReadInt (r, mod.entrytable.entry[0]);
  207. i := 0;
  208. WHILE i < nofentries DO
  209. INC(i);
  210. OFS.ReadInt(r, mod.entrytable.entry[i]);
  211. END ;
  212. (*Trace.StringLn("Entry Table done.");*)
  213. OFS.ReadInt (r, datasize);
  214. Heaps.Alloc(mod.dbase, datasize);
  215. base := mod.dbase; WHILE datasize # 0 DO SYSTEM.PUT (base, 0); DEC (datasize, 4); INC (base, 4) END;
  216. OFS.ReadInt (r, codelen); mod.size := codelen * 4;
  217. (*Trace.StringLn("Data Section done.");*)
  218. Heaps.Alloc(mod.pbase, mod.size);
  219. base := mod.pbase; WHILE codelen # 0 DO OFS.ReadInt (r, i); SYSTEM.PUT (base, i); DEC (codelen); INC (base, 4) END;
  220. FixSelf(mod.pbase, fixself, mod.pbase); i := 0;
  221. WHILE i < nofimp DO
  222. offset := import[i].pbase - mod.pbase;
  223. Fixup(mod.pbase, fixroot[i], (import[i].pbase - mod.pbase) DIV 4, import[i].pbase, import[i].entrytable.entry); INC(i);
  224. END;
  225. (*Trace.StringLn("Code Section done.");*)
  226. (*
  227. FOR i := 0 TO mod.size-1 BY 4 DO
  228. SYSTEM.GET(mod.pbase+i*4, j);
  229. END;
  230. *)
  231. (* make sure all the data is flushed before we try and call the program *)
  232. Caches.CleanDCacheRange( mod.pbase, mod.size );
  233. (*Trace.StringLn("Cache flushed.");*)
  234. Call ( mod, mod.entrytable.entry[0] );
  235. (*Trace.StringLn("Call done.");*)
  236. ELSE
  237. (* Failed to load module, therefore remove it from the list of loaded modules *)
  238. (* RemoveMod(mod); *)
  239. END;
  240. OFS.Close (f);
  241. END;
  242. END;
  243. END ThisMod;
  244. BEGIN
  245. SYSTEM.GET ( Platform.ModRoot, root );
  246. END Modules.