dec20-lap.red 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. %
  2. % 20-LAP.RED - Dec-20 PSL assembler
  3. %
  4. % Author: Eric Benson
  5. % Symbolic Computation Group
  6. % Computer Science Dept.
  7. % University of Utah
  8. % Date: 1 February 1982
  9. % Copyright (c) 1982 University of Utah
  10. %
  11. fluid '(LabelOffsets!* CurrentOffset!* CodeSize!* CodeBase!* Entries!*
  12. ForwardInternalReferences!*
  13. NewBitTableEntry!* LapReturnValue!*
  14. !*WritingFaslFile InitOffset!* !*PGWD !*PWrds);
  15. CompileTime <<
  16. flag('(SaveEntry DefineEntries DepositInstruction
  17. OpcodeValue OperandValue DepositWord DepositWordExpression
  18. DepositHalfWords LabelValue DepositItem DepositHalfWordIDNumber
  19. FindLabels OneLapLength MakeRelocInf MakeRelocWord),
  20. 'InternalFunction);
  21. smacro procedure LabelP X;
  22. atom X;
  23. >>;
  24. LoadTime <<
  25. !*PWrds := T;
  26. >>;
  27. lisp procedure Lap U;
  28. begin scalar LapReturnValue!*, LabelOffsets!*, Entries!*;
  29. if not !*WritingFaslFile then
  30. CurrentOffset!* := 0;
  31. U := Pass1Lap U;
  32. FindLabels U;
  33. if !*PGWD then for each X in U do
  34. if atom X then Prin2 X else PrintF(" %p%n", X);
  35. if not !*WritingFaslFile then
  36. CodeBase!* := GTBPS CodeSize!*;
  37. for each X in U do
  38. if not LabelP X then
  39. if first X = '!*entry then SaveEntry X
  40. else DepositInstruction X;
  41. DefineEntries();
  42. if not !*WritingFaslFile and !*PWrds then
  43. ErrorPrintF("*** %p: base %o, length %d words",
  44. for each X in Entries!* collect first car X,
  45. CodeBase!*, CodeSize!*);
  46. return MkCODE LapReturnValue!*;
  47. end;
  48. lisp procedure SaveEntry X;
  49. if second X = '!*!*!*Code!*!*Pointer!*!*!* then
  50. LapReturnValue!* := % Magic token that tells LAP to return
  51. (if !*WritingFaslFile then CurrentOffset!* % a code pointer
  52. else IPlus2(CodeBase!*, CurrentOffset!*))
  53. else if not !*WritingFaslFile then
  54. << Entries!* := (rest X . CurrentOffset!*) . Entries!*;
  55. if not LapReturnValue!* then LapReturnValue!* :=
  56. IPlus2(CodeBase!*, CurrentOffset!*) >>
  57. else if second X = '!*!*Fasl!*!*InitCode!*!* then
  58. InitOffset!* := CurrentOffset!*
  59. else if FlagP(second X, 'InternalFunction) then
  60. put(second X, 'InternalEntryOffset, CurrentOffset!*)
  61. else
  62. << FindIDNumber second X;
  63. DFPrintFasl list('PutEntry, MkQuote second X,
  64. MkQuote third X,
  65. CurrentOffset!*) >>;
  66. lisp procedure DefineEntries();
  67. for each X in Entries!* do
  68. PutD(first car X, second car X, MkCODE IPlus2(CodeBase!*, cdr X));
  69. lisp procedure DepositInstruction X;
  70. %
  71. % Legal forms are:
  72. % (special_form . any)
  73. % (opcode)
  74. % (opcode address)
  75. % (opcode ac address)
  76. %
  77. begin scalar Op, Y, A, E;
  78. return if (Y := get(first X, 'InstructionDepositFunction)) then
  79. Apply(Y, list X)
  80. else
  81. << NewBitTableEntry!* := 0;
  82. Op := OpcodeValue first X;
  83. if null(Y := rest X) then
  84. A := E := 0
  85. else
  86. << E := OperandValue first Y;
  87. if null(Y := rest Y) then
  88. A := 0
  89. else
  90. << A := E;
  91. E := OperandValue first Y >> >>;
  92. UpdateBitTable(1, NewBitTableEntry!*);
  93. DepositAllFields(Op, A, E) >>;
  94. end;
  95. lisp procedure DepositAllFields(Op, A, E);
  96. << @IPlus2(CodeBase!*, CurrentOffset!*) :=
  97. ILOR(ILSH(Op, 27), ILOR(ILSH(A, 23), E));
  98. CurrentOffset!* := IAdd1 CurrentOffset!* >>;
  99. lisp procedure OpcodeValue U;
  100. if PosIntP U then U
  101. else get(U, 'OpcodeValue) or StdError BldMsg("Unknown opcode %r", U);
  102. lisp procedure OperandValue U;
  103. %
  104. % Legal forms are:
  105. % number
  106. % other atom (label)
  107. % (special . any) fluid, global, etc.
  108. % (indexed register address)
  109. % (indirect other_op)
  110. %
  111. begin scalar X;
  112. return if PosIntP U then U
  113. else if NegIntP U then ILAND(U, 8#777777)
  114. else if LabelP U then LabelValue U
  115. else if (X := get(first U, 'OperandValueFunction)) then
  116. Apply(X, list U)
  117. else if (X := WConstEvaluable U) then OperandValue X
  118. else StdError BldMsg("Unknown operand %r", U);
  119. end;
  120. lisp procedure BinaryOperand U;
  121. %
  122. % (op x x) can occur in expressions
  123. %
  124. begin scalar X;
  125. return if (X := WConstEvaluable U) then X
  126. else
  127. << X := if GetD first U then first U else get(first U, 'DOFN);
  128. U := rest U;
  129. if NumberP first U then
  130. Apply(X, list(first U, LabelValue second U))
  131. else if NumberP second U then
  132. Apply(X, list(LabelValue first U, second U))
  133. else StdError BldMsg("Expression too complicated in LAP %r", U) >>;
  134. end;
  135. % Add others to this list if they arise
  136. put('difference, 'OperandValueFunction, 'BinaryOperand);
  137. put('WPlus2, 'OperandValueFunction, 'BinaryOperand);
  138. lisp procedure RegisterOperand U;
  139. begin scalar V;
  140. U := second U;
  141. return if PosIntP U then U
  142. else if (V := get(U, 'RegisterNumber)) then V
  143. else StdError BldMsg("Unknown register %r", U);
  144. end;
  145. put('REG, 'OperandValueFunction, 'RegisterOperand);
  146. DefList('((nil 0)
  147. (t1 6)
  148. (t2 7)
  149. (t3 8)
  150. (t4 9)
  151. (t5 10)
  152. (t6 11)
  153. (st 8#17)), 'RegisterNumber);
  154. lisp procedure ImmediateOperand U;
  155. OperandValue second U; % immediate does nothing on the PDP10
  156. put('immediate, 'OperandValueFunction, 'ImmediateOperand);
  157. lisp procedure IndexedOperand U;
  158. begin scalar V;
  159. V := OperandValue second U;
  160. U := OperandValue third U;
  161. return ILOR(ILSH(V, 18), U);
  162. end;
  163. put('indexed, 'OperandValueFunction, 'IndexedOperand);
  164. lisp procedure LapValueCell U;
  165. ValueCellLocation second U;
  166. DefList('((fluid LapValueCell)
  167. (!$fluid LapValueCell)
  168. (global LapValueCell)
  169. (!$global LapValueCell)), 'OperandValueFunction);
  170. lisp procedure LapEntry U;
  171. FunctionCellLocation second U;
  172. put('entry, 'OperandValueFunction, 'LapEntry);
  173. lisp procedure LapInternalEntry U;
  174. begin scalar X;
  175. U := second U;
  176. NewBitTableEntry!* := const RELOC_HALFWORD;
  177. return if (X := Atsoc(U, LabelOffsets!*)) then
  178. << X := cdr X;
  179. if !*WritingFaslFile then X else IPlus2(CodeBase!*, X) >>
  180. else
  181. << if not !*WritingFaslFile then FunctionCellLocation U
  182. else if (X := get(U, 'InternalEntryOffset)) then X
  183. else
  184. << ForwardInternalReferences!* :=
  185. (CurrentOffset!* . U) . ForwardInternalReferences!*;
  186. 0 >> >>; % will be modified later
  187. end;
  188. put('InternalEntry, 'OperandValueFunction, 'LapInternalEntry);
  189. lisp procedure DepositWordBlock X;
  190. for each Y in cdr X do DepositWordExpression Y;
  191. put('fullword, 'InstructionDepositFunction, 'DepositWordBlock);
  192. lisp procedure DepositHalfWordBlock X;
  193. begin scalar L, R;
  194. X := rest X;
  195. while not null X do
  196. << L := first X;
  197. X := rest X;
  198. if null X then
  199. R := 0
  200. else
  201. << R := first X;
  202. X := rest X >>;
  203. DepositHalfWords(L, R) >>;
  204. end;
  205. put('halfword, 'InstructionDepositFunction, 'DepositHalfWordBlock);
  206. CommentOutCode <<
  207. lisp procedure DepositByteBlock X;
  208. case length X of
  209. 0: DepositWord 0;
  210. 1: DepositBytes(first X, 0, 0, 0, 0);
  211. 2: DepositBytes(first X, second X, 0, 0, 0);
  212. 3: DepositBytes(first X, second X, third X, 0, 0);
  213. 4: DepositBytes(first X, second X, third X, fourth X, 0);
  214. default:
  215. << DepositBytes(first X, second X, third X, fourth X, fourth rest X);
  216. DepositByteBlock rest rest rest rest rest X >>;
  217. end;
  218. put('byte, 'InstructionDepositFunction, 'DepositByteBlock);
  219. >>;
  220. lisp procedure DepositString X;
  221. begin scalar Y;
  222. X := StrInf second X;
  223. Y := StrPack StrLen X;
  224. for I := 1 step 1 until Y do DepositWord @IPlus2(X, I);
  225. end;
  226. put('string, 'InstructionDepositFunction, 'DepositString);
  227. lisp procedure DepositFloat X; % this will not work in cross-assembly
  228. << X := second X; % don't need to strip tag on PDP10
  229. DepositWord FloatHighOrder X;
  230. DepositWord FloatLowOrder X >>;
  231. put('float, 'InstructionDepositFunction, 'DepositFloat);
  232. lisp procedure DepositWord X;
  233. << @IPlus2(CodeBase!*, CurrentOffset!*) := X;
  234. UpdateBitTable(1, 0);
  235. CurrentOffset!* := IAdd1 CurrentOffset!* >>;
  236. lisp procedure DepositWordExpression X; % Only limited expressions now handled
  237. begin scalar Y;
  238. return if FixP X then DepositWord Int2Sys X
  239. else if LabelP X then
  240. << @IPlus2(CodeBase!*, CurrentOffset!*) := LabelValue X;
  241. UpdateBitTable(1, const RELOC_HALFWORD);
  242. CurrentOffset!* := IAdd1 CurrentOffset!* >>
  243. else if first X = 'MkItem then DepositItem(second X, third X)
  244. else if first X = 'FieldPointer then
  245. DepositFieldPointer(second X, third X, fourth X)
  246. else if (Y := WConstEvaluable X) then DepositWord Int2Sys Y
  247. else StdError BldMsg("Expression too complicated %r", X);
  248. end;
  249. lisp procedure DepositHalfWords(L, R);
  250. begin scalar Y;
  251. if not (FixP L or (L := WConstEvaluable L))
  252. then StdError "Left half too complex";
  253. if PairP R and first R = 'IDLoc then
  254. DepositHalfWordIDNumber(L, second R)
  255. else if (Y := WConstEvaluable R) then DepositWord ILOR(ILSH(L, 18), Y)
  256. else StdError BldMsg("Halfword expression too complicated %r", R);
  257. end;
  258. lisp procedure LabelValue U;
  259. begin scalar V;
  260. return if CodeP U then Inf U
  261. else if (V := Atsoc(U, LabelOffsets!*)) then
  262. << V := cdr V;
  263. if !*WritingFaslFile then
  264. << NewBitTableEntry!* := const RELOC_HALFWORD;
  265. V >>
  266. else IPlus2(CodeBase!*, V) >>
  267. else StdError BldMsg("Unknown label %r in LAP", U);
  268. end;
  269. lisp procedure DepositItem(TagPart, InfPart);
  270. if not !*WritingFaslFile then
  271. DepositWord MkItem(TagPart, if LabelP InfPart then
  272. LabelValue InfPart
  273. else if first InfPart = 'IDLoc then
  274. IDInf second InfPart
  275. else
  276. StdError BldMsg("Unknown inf in MkItem %r",
  277. InfPart))
  278. else
  279. << if LabelP InfPart then
  280. @IPlus2(CodeBase!*, CurrentOffset!*) := % RELOC_CODE_OFFSET = 0
  281. MkItem(TagPart, LabelValue InfPart)
  282. else if first InfPart = 'IDLoc then
  283. @IPlus2(CodeBase!*, CurrentOffset!*) :=
  284. MkItem(TagPart,
  285. MakeRelocInf(const RELOC_ID_NUMBER,
  286. FindIDNumber second InfPart))
  287. else StdError BldMsg("Unknown inf in MkItem %r", InfPart);
  288. CurrentOffset!* := IAdd1 CurrentOffset!*;
  289. UpdateBitTable(1, const RELOC_INF) >>;
  290. lisp procedure DepositHalfWordIDNumber(LHS, X);
  291. if not !*WritingFaslFile or ILEQ(IDInf X, 128) then
  292. DepositWord ILOR(ILSH(LHS, 18), IDInf X)
  293. else
  294. << @IPlus2(CodeBase!*, CurrentOffset!*) := ILOR(ILSH(LHS, 18),
  295. MakeRelocHalfWord(const RELOC_ID_NUMBER, FindIDNumber X));
  296. CurrentOffset!* := IAdd1 CurrentOffset!*;
  297. UpdateBitTable(1, const RELOC_HALFWORD) >>;
  298. lisp procedure SystemFaslFixup();
  299. << while not null ForwardInternalReferences!* do
  300. << Field(@IPlus2(CodeBase!*,
  301. car first ForwardInternalReferences!*),
  302. 18, 18) :=
  303. get(cdr first ForwardInternalReferences!*, 'InternalEntryOffset)
  304. or << ErrorPrintF(
  305. "***** %r not defined in this module; normal function call being used",
  306. cdr first ForwardInternalReferences!*);
  307. MakeRelocHalfWord(const RELOC_FUNCTION_CELL,
  308. FindIDNumber cdr first
  309. ForwardInternalReferences!*) >>;
  310. ForwardInternalReferences!* := cdr ForwardInternalReferences!* >>;
  311. MapObl function lambda(X);
  312. RemProp(X, 'InternalEntryOffset) >>;
  313. fluid '(LapCodeList!*);
  314. lisp procedure FindLabels LapCodeList!*;
  315. << CodeSize!* := 0;
  316. for each X in LapCodeList!* do
  317. CodeSize!* := IPlus2(CodeSize!*, OneLapLength X) >>;
  318. lisp procedure OneLapLength U;
  319. begin scalar X;
  320. return if atom U then
  321. << LabelOffsets!* := (U . IPlus2(CurrentOffset!*, CodeSize!*))
  322. . LabelOffsets!*;
  323. 0 >>
  324. else if (X := get(car U, 'LapLength)) then
  325. if PosIntP X then X
  326. else Apply(X, list U)
  327. else % minor klugde for long constants
  328. << if length U = 3 and FixP(X := third U) and not ImmediateP X then
  329. begin scalar Y;
  330. RPlaca(rest rest U, Y := StringGensym());
  331. NConc(LapCodeList!*, list(Y, list('fullword, X)));
  332. end;
  333. 1 >>;
  334. end;
  335. DefList('((!*entry LapEntryLength)
  336. (float 2)
  337. (string LapStringLength)
  338. (fullword LapWordLength)
  339. (halfword LapHalfwordLength)
  340. (byte LapByteLength)), 'LapLength);
  341. lisp procedure LapEntryLength U;
  342. << LabelOffsets!* := (second U . IPlus2(CurrentOffset!*, CodeSize!*))
  343. . LabelOffsets!*;
  344. 0 >>;
  345. lisp procedure LapStringLength U;
  346. StrPack StrLen StrInf second U;
  347. lisp procedure LapWordLength U;
  348. length rest U;
  349. lisp procedure LapHalfwordLength U;
  350. ILSH(IAdd1 length rest U, -1);
  351. lisp procedure LapByteLength U;
  352. StrPack length rest U;
  353. on SysLisp;
  354. syslsp procedure DepositFieldPointer(Opr, Start, Len);
  355. << LispVar NewBitTableEntry!* := 0;
  356. Opr := OperandValue Opr;
  357. @IPlus2(LispVar CodeBase!*, LispVar CurrentOffset!*) :=
  358. ILOR(ILSH(36 - (Start + Len), 30), ILOR(ILSH(Len, 24), Opr));
  359. UpdateBitTable(1, LispVar NewBitTableEntry!*);
  360. LispVar CurrentOffset!* := IAdd1 LispVar CurrentOffset!* >>;
  361. syslsp procedure IndirectOperand U;
  362. ILOR(ILSH(1, 22), OperandValue second U);
  363. put('Indirect, 'OperandValueFunction, 'IndirectOperand);
  364. % ExtraRegLocation is in 20-FASL
  365. put('ExtraReg, 'OperandValueFunction, 'ExtraRegLocation);
  366. syslsp procedure MakeRelocWord(RelocTag, RelocInf);
  367. LSH(RelocTag, 34) + Field(RelocInf, 2, 34);
  368. syslsp procedure MakeRelocInf(RelocTag, RelocInf);
  369. LSH(RelocTag, 16) + Field(RelocInf, 20, 16);
  370. syslsp procedure MakeRelocHalfWord(RelocTag, RelocInf);
  371. LSH(RelocTag, 16) + Field(RelocInf, 20, 16);
  372. off SysLisp;
  373. END;