dec20-lap.red 13 KB

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