examples-for-imp-guide.mss 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. @section(Examples of various kinds)
  2. Recall that when compiling code, variables which are used extended in
  3. one procedure, and bound as LAMBDA or PROG variables in another, must
  4. be declared fluids.
  5. Example:
  6. @begin(verbatim)
  7. (de foo(X) (PLUS2 X 1)), compiles to:
  8. (!*entry foo expr 1)
  9. (!*alloc 0)
  10. (!*move (quote 1) (reg 2))
  11. (!*linke 0 plus2 expr 2)
  12. (de fee(X Y) (Fum (foo X) (foo Y)), compiles to:
  13. (!*entry fee expr 2)
  14. (!*alloc 2)
  15. (!*move (reg 2) (frame 2))
  16. (!*link foo expr 1)
  17. (!*move (reg 1) (frame 1))
  18. (!*move (frame 2) (reg 1))
  19. (!*link foo expr 1)
  20. (!*move (reg 1) (reg 2))
  21. (!*move (frame 1) (reg 1))
  22. (!*linke 2 fum expr 2)
  23. Finally, (de fac (N) (cond ((Lessp N 1) 1)
  24. (T (Times2 N (fac SUB 1 N))
  25. compiles to:
  26. (!*entry fac expr 1)
  27. (!*alloc 1)
  28. (!*move (reg 1) (frame 1))
  29. (!*move (quote 1) (reg 2))
  30. (!*link LessP expr 1)
  31. (!*jumpeq (label L) (quote nil) (reg 1))
  32. (!*move (quote 1) (reg 1))
  33. (!*exit 1)
  34. (!*lbl (label L))
  35. (!*move (frame 1) (reg 1))
  36. (!*link sub1 expr 1)
  37. (!*link fac expr 1)
  38. (!*move (reg 1) (reg 2))
  39. (!*move (frame 1) (reg 1))
  40. (!*linke 1 times2 expr 2)
  41. @end(verbatim)
  42. @section(BUILDING the CROSS Compiler)
  43. The executable @dq[xxxx-CROSS.EXE] is built as follows:
  44. @begin(verbatim)
  45. @@psl:rlisp ! an RLISP
  46. *mapobl function lambda X;
  47. *<< RemProp(X, 'OpenCode);
  48. * RemProp(X, 'ExitOpenCode) >>; % Remove old compiler opts
  49. * % Load common modules
  50. *load(zboot, pass!-one!-lap, if!-system, syslisp, lap!-to!-asm);
  51. * % Load XXXX specific modules
  52. *load(XXXX!-comp, XXXX!-cmac, XXXX!-asm);
  53. *off UserMode;
  54. *DumpFileName!* := "filename.exe"; % Establish the executable name
  55. *Date!*:=Concat("XXXX Cross Assmbler ", Date()); % Establish greeting
  56. *DumpLisp(); % Does a Reclaim and save
  57. *Quit;
  58. @end(verbatim)
  59. @subsection(An example of the process)
  60. The following is a complete example, from @syslisp to @CMACRO@xs:
  61. @begin(verbatim,leftmargin 0)
  62. @@PSL:RLISP
  63. PSL 3.0 Rlisp, 9-May-82
  64. syslsp procedure Test1(); % Input RLISP syntax code
  65. begin scalar x;
  66. x := 5;
  67. x := x+7;
  68. L := '(A B C D);
  69. L1 := (CAR L) . CAR(CDR L);
  70. print L1;
  71. end;
  72. @End(verbatim)
  73. @begin(verbatim,leftmargin 0)
  74. % This is the output from the Compiler/LAP system.
  75. % The lines beginning with "(!* ... " are the Abstract
  76. % machine CMACRO's output from the compiler.
  77. % The indented lines following them are the VAX @sq[LAP]
  78. % assembly code the CMACRO patterns
  79. % (in the *-CMAC.SL files) produced by the expansion process.
  80. (!*PUSH '5)
  81. (@op{PUSHL} 5)
  82. (!*WPLUS2 (FRAME 1) (WCONST 7)) % WPLUS2 is actually a
  83. % CMACRO (OpenFunct)
  84. (@op{ADDL2} 7 (DEFERRED (REG ST))) % Note how the FRAME AnyReg
  85. % is converted directly to
  86. % a machine specific
  87. % addressing mode.
  88. (!*MOVE '(A B C D) (!$FLUID L))
  89. (@op{MOVL} '(A B C D) (!$FLUID L))
  90. (!*MOVE (CAR (CDR (!$FLUID L))) (REG 2))
  91. % The AnyReg patterns
  92. (@op{EXTZV} 0 27 (!$FLUID L) (REG 2)) % for CAR and CDR are used
  93. (@op{EXTZV} 0 27 (DISPLACEMENT (REG 2) 4) (REG 2))
  94. (@op{MOVL} (DEFERRED (REG 2)) (REG 2))
  95. (!*MOVE (CAR (!$FLUID L)) (REG 1))
  96. (@op{EXTZV} 0 27 (!$FLUID L) (REG 1))
  97. (@op{MOVL} (DEFERRED (REG 1)) (REG 1))
  98. (!*LINK CONS EXPR 2) % Standard Function Cell
  99. % call.
  100. (@op{JSB} (ENTRY CONS))
  101. (!*MOVE (REG 1) (!$FLUID L1))
  102. (@op{MOVL} (REG 1) (!$FLUID L1))
  103. (!*LINK PRINT EXPR 1)
  104. (@op{JSB} (ENTRY PRINT))
  105. (!*MOVE 'NIL (REG 1))
  106. (@op{MOVL} (REG NIL) (REG 1)) % Reg NIL evaluates to an
  107. (!*EXIT 1) % immediate constant.
  108. (@op{ADDL2} 4 (REG ST))
  109. (@op{RSB})
  110. TEST1
  111. @end(verbatim)
  112. @subsection(Prologues and Epilogues)
  113. An example of Prologues and Epilogues for (@APOLLO version of) the
  114. @68000 is given below:
  115. @begin(ProgramExample,leftmargin 0)
  116. lisp procedure CodeFileHeader(); % Pure Code Segment
  117. If !*MAIN then
  118. <<CodePrintF(" program %w,m0001%n",ModName!*);
  119. CodePrintF " data%n";
  120. DataProcState!*:='data;
  121. CodePrintF "* Start of execution of the program%n";
  122. CodeDeclareExternal 'SYMVAL; %/ Issue EXTERN.D early
  123. CodeDeclareExternal 'SYMFNC; %/ Issue EXTERN.D early
  124. CodePrintF "m0001 EQ *%n";
  125. CodePrintF " move.l db,-(sp) Save caller db%n";
  126. CodePrintF " clr.l -(sp) Push reserved word%n";
  127. CodePrintF " move.l a0,-(sp) Push address of ECB%n";
  128. CodePrintF " move.l SYMVAL+512,d0 Init NIL Reg%n";
  129. CodePrintF " link sb,#0 Balance unlink%n";
  130. CodePrintF " movea.l #0,a6 Setup zeroareg%n";
  131. CodePrintF " lea m0001,db Setup db reg%n";
  132. CodePrintF(" jsr %w Call Main routine%n",
  133. MainEntryPointNAme!*);
  134. CodePrintF "* now return to OS%n";
  135. CodePrintF " movea.l A_PGM_$EXIT,a6%n";
  136. CodePrintF " jsr (a6)%n";
  137. CodePrintF " unlk sb Reload callers SB%n";
  138. CodePrintF " addq.w #8,sp Pop linkage%n";
  139. CodePrintF " movea.l (sp)+,db Reload callers db%n";
  140. CodePrintF " rts Return%n";
  141. ForeignExternList!*:=NIL;
  142. CheckForeignExtern 'PGM!_!$EXIT;
  143. >>
  144. else
  145. <<CodePrintF (" module %w,m0000%n",ModName!*);
  146. %/ Kludge, since ModuleName set in ASMOUT
  147. CodePrintF " data%n";
  148. DataProcState!*:='data;
  149. CodeDeclareExternal 'SYMVAL; %/ Issue EXTERN.D early
  150. CodeDeclareExternal 'SYMFNC; %/ Issue EXTERN.D early
  151. CodePrintF "* this is an Independent Module %n";
  152. ForeignExternList!*:=NIL;
  153. >>;
  154. lisp procedure DataFileHeader();
  155. Begin
  156. DataPrintF(" module %w_D%n",ModName!*);
  157. DataPrintF " data%n";
  158. End;
  159. lisp procedure DataFileTrailer();
  160. DataPrintF "end%n";
  161. lisp procedure CodeFileTrailer();
  162. <<Foreach Fn in Reverse ForeignExternList!* do
  163. <<CodePrintF(" extern.p %w%n",Fn);
  164. CodePrintF("A_%w ac %w%n",Fn,Fn)>>;
  165. CodePrintF " end%n">>;
  166. @end(ProgramExample)
  167. The general use of the headers given above is to declare the module
  168. name, tell the assembler that this is a data section@Foot[On the @Apollo
  169. all of the code and data were put in a data section since the operating
  170. system and assembler had a problem with mixed code and data due to
  171. expecting a pure code segment with all data references relative to the data
  172. base register.], and in the
  173. case of the main routine performing the proper operating system dependent
  174. linkage for program entry and exit.
  175. Note that CodePrintF and DataPrintF are used to direct output to
  176. either the @ei[code] segment or @ei[data] segment. This is to allow
  177. seperate segements for those machines that allow for pure code segments (on
  178. the @Apollo a pure code segment is directly maped into the address space
  179. rather than copied, which results in a large difference in start up speed).
  180. This could probably be extended to PureCode, PureData, and ImpureData.
  181. procedure WW(X);
  182. <<print LIST('WW,x); x+1>>;
  183. Now a plain resolve function.
  184. That does not argument processing
  185. best for register conversion:
  186. procedure MYREGFN(R,S);
  187. <<Print LIST('MYREG, R,S);
  188. List('REG,S+10)>>;
  189. PUT('MYREG,'ANYREGRESOLUTIONFUNCTION,'MYREGFN);
  190. procedure MYANYFN(R,S);
  191. <<Print LIST('MYANY, R,S);
  192. S:= ResolveOperand('(REG t3),S);
  193. List('Weird,S)>>;
  194. FLAG('(WEIRD),'TERMINALOPERAND);
  195. PUT('MYANY,'ANYREGRESOLUTIONFUNCTION,'MYANYFN);
  196. (!*MOVE (WW 1) (WW 2))); ARgs must be WCONSTEVALUABEL
  197. (!*MOVE (WW (WW 1)) (WW 2)));
  198. (!*MOVE (WW A) (WW 2))); % First WW shouldnt convert
  199. (!*MOVE (MYREG 1) (MYREG 2))); % OK
  200. (!*MOVE (MYREG (WW 1)) (WW (MYREG 2)))); % Fails since args not processed
  201. (!*MOVE (MYREG (MYREG 1)) (MYREG 2)));
  202. (!*MOVE (MYANY 1) (MYANY 2))); % OK
  203. (!*MOVE (MYANY (WW 1)) (MYANY (MYREG 2)))); % Args processed
  204. (!*MOVE (MYANY (MYANY 1)) (MYANY 2)));
  205. @section(Sample ANYREGs and CMACROs from various machines)
  206. The following choice pieces from the @VAX750, @DEC20 and @68000
  207. illustrate a range of addressing modes, predicates and style.
  208. @subsection(VAX)
  209. @begin(verbatim,leftmargin 0)
  210. (DefCMacro !*Move % ARGONE -> ARGTWO
  211. (Equal) % Don't do anything
  212. ((ZeroP AnyP) (@op{clrl} ARGTWO)) % 0 -> ARGTWO
  213. ((NegativeImmediateP AnyP) % -n -> ARGTWO
  214. (@op{mnegl} (immediate (minus ARGONE)) ARGTWO))
  215. ((@op{movl} ARGONE ARGTWO))) % General case
  216. (DefCMacro !*WPlus2 % ARGONE+ARGTWO->ARGONE
  217. ((AnyP OneP) (@op{incl} ARGONE)) % add 1
  218. ((AnyP MinusOneP) (@op{decl} ARGONE)) % Subtract 1
  219. ((AnyP MinusP) (@op{subl2} (immediate (minus ARGTWO)) ARGONE))
  220. ((@op{addl2} ARGTWO ARGONE)))
  221. The Predicates used:
  222. @begin(description,spread 0)
  223. Equal@\As an atom, rather than in (...), it check both arguments same.
  224. Zerop@\Check if argument is 0
  225. AnyP@\Just returns T
  226. NegativeImmediateP@\Check that a negative, 32 bit constant.
  227. @end(Description)
  228. @end(verbatim)
  229. @subsection(DEC-20)
  230. @begin(verbatim,leftmargin 0)
  231. (DefCMacro !*Move % Move ArgOne -> ArgTwo
  232. (Equal)
  233. ((ZeroP AnyP) (@op{setzm} ARGTWO))
  234. ((MinusOneP AnyP) (@op{setom} ARGTWO))
  235. ((RegisterP AnyP) (@op{movem} ARGONE ARGTWO))
  236. ((NegativeImmediateP RegisterP)
  237. (@op{movni} ARGTWO (immediate (minus ARGONE))))
  238. ((ImmediateP RegisterP) (@op{hrrzi} ARGTWO ARGONE))
  239. ((AnyP RegisterP) (@op{move} ARGTWO ARGONE))
  240. ((!*MOVE ARGONE (reg t1)) (@op{movem} (reg t1) ARGTWO)))
  241. (DefCMacro !*WPlus2
  242. ((AnyP OneP) (@op{aos} ARGONE))
  243. ((AnyP MinusOneP) (@op{sos} ARGONE))
  244. ((AnyP RegisterP) (@op{addm} ARGTWO ARGONE))
  245. ((RegisterP NegativeImmediateP)
  246. (@op{subi} ARGTWO (minus ARGONE)))
  247. ((RegisterP ImmediateP) (@op{addi} ARGTWO ARGONE))
  248. ((RegisterP AnyP) (@op{add} ARGONE ARGTWO))
  249. ((!*MOVE ARGTWO (reg t2)) (@op{addm} (reg t2) ARGONE)))
  250. The Predicates used:
  251. @begin(description,spread 0)
  252. Equal@\As an atom, rather than in (...), it check both arguments same.
  253. Zerop@\Check if argument is 0
  254. AnyP@\Just returns T
  255. MinusOneP@\Check that argument is -1.
  256. ImmediateP@\Check that an address or 18 bit constant. Will
  257. change for extended addressing.
  258. NegativeImmediateP@\Check that a negative 18 bit constant.
  259. RegisterP@\Check that is (REG r), a register.
  260. @end(Description)
  261. @end(verbatim)
  262. @subsection(APOLLO)
  263. @begin(verbatim,leftmargin 0)
  264. (DefCMacro !*Move % (!*Move Source Destination)
  265. (Equal) % if source @Value(Eq) dest then do nothing
  266. ((ZeroP AregP)(@op{suba!.l} ARGTWO ARGTWO))
  267. ((ZeroP AnyP) (@op{clr!.l} ARGTWO)) % if source @Value(Eq) 0 then dest := 0
  268. ((InumP AregP) (@op{movea!.l} (Iconst ARGONE) ARGTWO))
  269. ((AddressP AregP) (@op{lea} ARGONE ARGTWO))
  270. ((InumP AnyP) (@op{move!.l} (Iconst ARGONE) ARGTWO))
  271. ((AddressP AnyP)
  272. (lea ARGONE (reg a0)) (@op{move!.l} (reg a0) ARGTWO))
  273. ((AnyP AregP) (@op{movea!.l} ARGONE ARGTWO))
  274. ((@op{move!.l} ARGONE ARGTWO)))
  275. (DefCMacro !*WPlus2 % (!*WPlus2 dest source)
  276. ((AnyP QuickIconstP) (@op{addq!.l} (Iconst ARGTWO) ARGONE))
  277. ((AnyP NegativeQuickIconstP)
  278. (@op{subq!.l} (Iconst (minus ARGTWO)) ARGONE))
  279. ((AregP MinusP) (@op{suba!.l} (Iconst (Minus ARGTWO)) ARGONE))
  280. ((AnyP MinusP) (@op{subi!.l} (Minus ARGTWO) ARGONE))
  281. ((AregP InumP) (@op{adda!.l} (Iconst ARGTWO) ARGONE))
  282. ((AnyP InumP) (@op{addi!.l} (Iconst ARGTWO) ARGONE))
  283. ((AregP AddressP) (@op{lea} ARGTWO (reg a0))
  284. (@op{adda!.l} (reg a0) ARGONE))
  285. ((AnyP AddressP) (@op{lea} ARGTWO (reg a0))
  286. (@op{add!.l} (reg a0) ARGONE))
  287. ((AregP AnyP)(@op{adda!.l} ARGTWO ARGONE))
  288. ((@op{add!.l} ARGTWO ARGONE))) % really need one a DREG
  289. The Predicates used:
  290. @begin(description,spread 0)
  291. Equal@\As an atom, rather than in (...), it check both arguments same.
  292. Zerop@\Check if argument is 0
  293. AregP@\Check that is one of the A registers (which can not be used for
  294. arithmetic), and require modified mnemonics.
  295. DregP@\Check that is one of the D registers, used for most
  296. arithmetic.
  297. InumP@\Check that a small integer.
  298. AddressP@\Check that an address, not a constant, since we need to use
  299. different instruction for Address's, e.g@. @op{lea} vs @op{movi}.
  300. AnyP@\Just returns T.
  301. NegativeImmediateP@\Check that a negative, 32 bit constant.
  302. QuickIconstP@\Small integer in range 1 ..@. 8 for the xxxxQ instructions on
  303. 68000.
  304. NegativeQuickIconstP@\Small integer in range -8 ..@. -1 for the xxxxQ
  305. instructions on 68000.
  306. @end(Description)
  307. @end(verbatim)
  308. @begin(verbatim,leftmargin 0)
  309. For example, on the @VAX750:
  310. @begin(Group)
  311. (DefAnyreg CAR % First ITEM of pair
  312. AnyregCAR % Associated function
  313. ((@op{extzv} 0 27 SOURCE REGISTER)
  314. % Code to extract 27 bit
  315. % address, masking TAG
  316. (Deferred REGISTER))) % Finally indexed mode used
  317. @hinge
  318. (DefAnyreg CDR % Second item
  319. AnyregCDR
  320. ((@op{extzv} 0 27 SOURCE REGISTER)
  321. (Displacement REGISTER 4)))
  322. % Displace 4 bytes off Register
  323. % Both CAR and CDR use a single instruction, so do not use a
  324. % predicate to test SOURCE.
  325. @hinge
  326. (DefAnyreg QUOTE % Note a set of different choices
  327. AnyregQUOTE
  328. ((Null) (REG NIL))
  329. ((EqTP) (FLUID T))
  330. ((InumP) SOURCE)
  331. ((QUOTE SOURCE)))
  332. @hinge
  333. (DefCMACRO !*Move % !*MOVE Usually has the most cases
  334. (Equal)
  335. ((ZeroP AnyP) (@op{clrl} ARGTWO))
  336. ((NegativeImmediateP AnyP)
  337. (@op{mnegl} (immediate (minus ARGONE)) ARGTWO))
  338. ((@op{movl} ARGONE ARGTWO)))
  339. @hinge
  340. (DefCMACRO !*Alloc
  341. ((ZeroP)) % No BODY - nothing to allocate
  342. ((@op{subl2} ARGONE (REG st))))
  343. @end(group)
  344. @end(verbatim)