faslin.red 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. on SysLisp;
  2. external WString TokenBuffer;
  3. external WArray ArgumentBlock;
  4. internal WConst CODE_OFFSET = 0,
  5. RELOC_ID_NUMBER = 1,
  6. RELOC_VALUE_CELL = 2,
  7. RELOC_FUNCTION_CELL = 3;
  8. internal WConst RELOC_WORD = 1,
  9. RELOC_RIGHT_HALF = 2,
  10. RELOC_INF = 3;
  11. internal WConst FASLMAGIC = 99;
  12. CompileTime <<
  13. smacro procedure LocalIDNumberP U;
  14. U >= 2048;
  15. smacro procedure LocalToGlobalID U;
  16. IDTable[U - 2048];
  17. smacro procedure ExtraArgumentP U;
  18. U >= 8150; % Something enough less than 8192
  19. smacro procedure MakeExtraArgument U;
  20. U - (8150 + (MaxRealRegs + 1));
  21. >>;
  22. internal WVar CodeBase;
  23. syslsp procedure FaslIN File;
  24. begin scalar F, N, M, IDTable, CodeSize, OldCodeBase,
  25. E, BT, R, RT, RI, BI, Top, BTop;
  26. F := BinaryOpenRead File;
  27. N := BinaryRead F; % First word is magic number
  28. if N neq FASLMAGIC then ContError(99,
  29. "%r is not a fasl format file",
  30. File,
  31. FaslIN File);
  32. M := BinaryRead F; % Number of local IDs
  33. Top := GtWArray 0; % pointer to top of space
  34. IDTable := GtWArray(M + 1); % Allocate space for table
  35. for I := 0 step 1 until M do
  36. << TokenBuffer[0] := BinaryRead F; % word is length of ID name
  37. BinaryReadBlock(F, &TokenBuffer[1], StrPack TokenBuffer[0]);
  38. IDTable[I] := IDInf Intern MkSTR TokenBuffer >>;
  39. CodeSize := BinaryRead F; % Size of code segment in words
  40. OldCodeBase := CodeBase; % So FASLIN is reentrant
  41. CodeBase := GtBPS CodeSize; % Allocate space in BPS
  42. BTop := GTBPS 0; % pointer to top
  43. E := CodeBase + BinaryRead F; % Next word is offset of init function
  44. % Will be called after code is read
  45. BinaryReadBlock(F, CodeBase, CodeSize); % Put the next N words there
  46. N := BinaryRead F; % Next word is size of bit table in words
  47. BT := GtWArray N; % Allocate space for bit table
  48. BinaryReadBlock(F, BT, N); % read bit table
  49. BinaryClose F; % close the file
  50. CodeSize := CodeSize*AddressingUnitsPerItem - 1;
  51. for I := 0 step 1 until CodeSize do
  52. << R := BitTable(BT, I);
  53. BI := CodeBase + I;
  54. case R of
  55. RELOC_WORD:
  56. << RT := RelocWordTag @BI;
  57. RI := RelocWordInf @BI;
  58. case RT of
  59. CODE_OFFSET:
  60. @BI := CodeBase + RI;
  61. RELOC_VALUE_CELL:
  62. << if ExtraArgumentP RI then
  63. RI := &ArgumentBlock[MakeExtraArgument RI]
  64. else if LocalIDNumberP RI then
  65. RI := &SymVal LocalToGlobalID RI
  66. else RI := &SymVal RI;
  67. @BI := RI >>;
  68. RELOC_FUNCTION_CELL:
  69. << if LocalIDNumberP RI then RI := LocalToGlobalID RI;
  70. @BI :=
  71. SymFnc + AddressingUnitsPerFunctionCell*RI >>;
  72. RELOC_ID_NUMBER: % Must be a local ID number
  73. << if LocalIDNumberP RI then RI := LocalToGlobalID RI;
  74. @BI := RI >>;
  75. end >>;
  76. RELOC_RIGHT_HALF:
  77. << RT := RelocRightHalfTag @BI;
  78. RI := RelocRightHalfInf @BI;
  79. case RT of
  80. CODE_OFFSET:
  81. RightHalf @BI := CodeBase + RI;
  82. RELOC_VALUE_CELL:
  83. << if ExtraArgumentP RI then
  84. RI := &ArgumentBlock[MakeExtraArgument RI]
  85. else if LocalIDNumberP RI then
  86. RI := &SymVal LocalToGlobalID RI
  87. else RI := &SymVal RI;
  88. RightHalf @BI := RI >>;
  89. RELOC_FUNCTION_CELL:
  90. << if LocalIDNumberP RI then RI := LocalToGlobalID RI;
  91. RightHalf @BI :=
  92. SymFnc + AddressingUnitsPerFunctionCell*RI >>;
  93. RELOC_ID_NUMBER: % Must be a local ID number
  94. << if LocalIDNumberP RI then RI := LocalToGlobalID RI;
  95. RightHalf @BI := RI >>;
  96. end >>;
  97. RELOC_INF:
  98. << RT := RelocInfTag @BI;
  99. RI := RelocInfInf @BI;
  100. case RT of
  101. CODE_OFFSET:
  102. Inf @BI := CodeBase + RI;
  103. RELOC_VALUE_CELL:
  104. << if ExtraArgumentP RI then
  105. RI := &ArgumentBlock[MakeExtraArgument RI]
  106. else if LocalIDNumberP RI then
  107. RI := &SymVal LocalToGlobalID RI
  108. else RI := &SymVal RI;
  109. Inf @BI := RI >>;
  110. RELOC_FUNCTION_CELL:
  111. << if LocalIDNumberP RI then RI := LocalToGlobalID RI;
  112. Inf @BI :=
  113. SymFnc + AddressingUnitsPerFunctionCell*RI >>;
  114. RELOC_ID_NUMBER: % Must be a local ID number
  115. << if LocalIDNumberP RI then RI := LocalToGlobalID RI;
  116. Inf @BI := RI >>;
  117. end >>;
  118. end >>;
  119. DelWArray(BT, Top);
  120. % return the space used by tables
  121. AddressApply0 E; % Call the init routine
  122. CodeBase := OldCodeBase; % restore previous value for CodeBase
  123. DelBPS(E, BTop); % deallocate space of init routine
  124. end;
  125. syslsp procedure PutEntry(Name, Type, Offset);
  126. PutD(Name, Type, MkCODE(CodeBase + Offset));
  127. off Syslisp;
  128. END;