OSDN Git Service

still trying to make the sieve stuff work.
[bif-6809/bif-6809.git] / BIFDOC.TXT~
1 \r
2                            BIF Documentation\r
3                           By Joel Matthew Rees\r
4                             19 January 1992, \r
5                               8 April 2019\r
6 \r
7 \r
8 BIF documentation Copyright  1992, 2000, 2019 Joel Matthew Rees\r
9 BIF source and object Copyright 1992, 2000, 2019 Joel Matthew Rees\r
10 https://ja.osdn.net/projects/bif-6809/\r
11 \r
12 \r
13 In the spirit of fig-FORTH, the author grants permission as follows:\r
14 =========\r
15 Permission to use, copy, modify, and/or distribute this software for \r
16 any purpose with or without fee is hereby granted, provided that the \r
17 accompanying copyright notices and this permission notice appear in \r
18 all copies.\r
19 \r
20 THE SOFTWARE IS PROVIDED “AS IS” AND ISC DISCLAIMS ALL WARRANTIES \r
21 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF \r
22 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY \r
23 SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES \r
24 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN \r
25 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, \r
26 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS \r
27 SOFTWARE.\r
28 =========\r
29 (This is essentially the ISC license.)\r
30 \r
31 If the copyright notices in this file and the README.TXT file are \r
32 retained, including that file and this with your distribution will\r
33 fulfill the copyright notice obligation.\r
34 \r
35 But you really should include both anyway, just to be kind to the \r
36 people who receive it.\r
37 \r
38 Note that:\r
39 \r
40 BIF is architecturally derived from fig-FORTH.  fig-FORTH comes courtesy\r
41 of the FORTH INTEREST GROUP, PO Box 1105, San Carlos, CA 94070.\r
42 \r
43 This is not a commercial product; it was a student project, use it at\r
44 your own risk.  No warranty whatsoever is made concerning it.  (If, by\r
45 chance, anyone is interested in using BIF in a commercial product, I\r
46 would appreciate knowing about it in advance.) The author's intent is\r
47 only to make it available for experimentation, and it should be treated\r
48 as strictly experimental software.  DO NOT ATTEMPT TO ACCESS ORDINARY\r
49 DISKS FORMATTED FOR USE BY OTHER OPERATING SYSTEMS WHILE BIF IS RUNNING!\r
50 \r
51 Contact as of January 2000:\r
52                                         http://reiisi.blogspot.com\r
53                                         joel.rees+knock@gmail.com\r
54                                         https://defining-computers.blogspot.com/\r
55                                         https://ja.osdn.net/users/reiisi/\r
56                                         https://sourceforge.net/u/reiisi/profile/\r
57                                         \r
58 \r
59 \r
60 *******************************************************************************\r
61                           General Information\r
62 \r
63 \r
64 BIF (BInary tree, fig-FORTH) is a dialect of FORTH for the Tandy Color\r
65 Computer.  It is a direct-threaded version of the pre-FORTH-79 fORTH\r
66 interest group publication of FORTH (fig-FORTH), using a non-standard\r
67 binary tree dictionary structure.  The direct-threading mechanism uses\r
68 the direct-page addressing mode of the 6809, and thus may not be easily\r
69 adaptable to FORTH-83.  It also uses absolute addressing, and thus does\r
70 not comform to the requirements of OS-9.  (I am working on an\r
71 indirect-threaded version of BIF for OS-9 in my spare time.)\r
72 \r
73 BIF.BIN is the executable object; after LOADMing it, EXEC the address\r
74 &H1300 (see below).  BIFSOURC.ARC contains the archived (TC31) source\r
75 files; the assembler used is Disk EDTASM+.  I used TSEdit to generate\r
76 the source files in EDTASM+ format:\r
77 \r
78 line-number SPACE [label] TAB mnemonic etc. LF\r
79 \r
80 Using a text editor to replace the macros with their expansions should\r
81 make it compatible with most other assemblers.  An object which will run\r
82 under the EDTASM+ "stand-alone" debugger may be generated by changing\r
83 ORG $1200 in BIF.ASM to ORG $3F00.\r
84 \r
85 BIFSCREE.ARC contains the BIF/FORTH source for several utilities, the\r
86 assembler, and double integer definitions (TOOLS.G00) and a definition\r
87 pairing example (PAIRS.G28) useful for making paired lists.  Using\r
88 TOOLS.G00 and PAIRS.G28 directly will require moving the two files to\r
89 their original granules, 0 and 28, on an ECB disk.  Once they are moved,\r
90 protecting the BIF screens with ECB directory entries may be a good\r
91 idea.  But resist the temptation to use a text editor on them.  Messing\r
92 with the whitespace will move the source code out of alignment with the\r
93 physical FORTH/BIF screens, and thus cause the source code not to load.\r
94 \r
95 If you want to look at these two files with an editor, I suggest copying\r
96 them to a different disk and looking at the copies.  Even my favorite\r
97 IBM PC editor, QEDIT, will insert a CR/LF at the end of every 512 bytes\r
98 on saving, which is not good.  (I wonder how many letters from OS-9\r
99 users it would take to convince the folks at SEMWARE/Applied Systems\r
100 Technologies to make an OS-9 version of their editor?)\r
101 \r
102 For $5.00, to cover postage, time, and the cost of floppies, I will send\r
103 a copy of the BIF screens disk on a standard 5 1/4" (ECB formatted)\r
104 floppy.  If you request the EDTASM+ compatible source code, I will send\r
105 that as well, on the same format disks.  For $5.00 more, I will include\r
106 a photo-copy of the documentation (useful if you don't have a way to\r
107 print it).\r
108 \r
109 The documentation which follows is written in the standard FORTH\r
110 documentation style.  It is not intended as a primer or study guide.\r
111 Brodie's Starting FORTH, Winfield's THE COMPLETE FORTH, or some other\r
112 text is suggested to those unfamiliar with FORTH.  Much of the code and\r
113 examples should work as shown in the textbooks I recommend Leo Brodie's\r
114 work, because he points out most of the places the user will have to\r
115 refer to this documentation.  Some of the descriptions are incomplete,\r
116 particularly where definitions are intended to be used inside other\r
117 definitions.\r
118 \r
119 The object contains a simple one-sector editor (for 32-column screens)\r
120 in the EDITOR vocabulary.  It does not provide search and replace, but\r
121 it is sufficient, for the patient, to write code.  My apologies for it.\r
122 I did not have a Color Computer 3 when I wrote the original code, and\r
123 haven't had the time to update it.  Those with access to the fig-FORTH\r
124 Installation Manual should have no problem installing the editor shown\r
125 there.\r
126 \r
127 The assembler in the BIF screens is a full postfix assembler.  The\r
128 double integer screens show a quick example of its use.\r
129 \r
130 \r
131 *******************************************************************************\r
132                           Getting BIF Running\r
133 \r
134 \r
135 Before you start, remember that BIF has the same post-fix grammar as\r
136 FORTH.  Think Reverse Polish, as in HP calculators.\r
137 \r
138 Computer:       Comments:\r
139 \r
140                 In Disk ECB, type:\r
141 LOADM "BIF.BIN" from whichever drive it is on, then remove all disks and\r
142 EXEC &H1300     BIF should tell you it is running with\r
143 6809 BIF V1.0\r
144 OK\r
145                 At this point, see if BIF is really running by typing\r
146 VLIST           and hitting ENTER.  You should see a listing of your\r
147                 main vocabulary (symbol table) which should run on for\r
148                 about 200 entries, and then the computer responds with\r
149 OK              If this doesn't happen, you have a bad object file, get\r
150                 a new copy.  Otherwise, you have BIF!\r
151 \r
152                 If you have my BIF screens disk, put it in drive 0.\r
153                 Then type\r
154 6 LOAD          to load the utilities starting at screen 6.  After the\r
155                 utilities are loaded, you can load the assembler by\r
156                 typing\r
157 DECIMAL 16 LOAD\r
158 \r
159                 If you don't have the BIF screens disk with the error\r
160                 messages, type\r
161 0 WARNING !     and BIF responds with\r
162 OK              but now tells you error numbers instead of messages.\r
163 \r
164 Okay, a few examples:\r
165 \r
166         42 EMIT\r
167 \r
168 puts the ascii character 42 (asterisk if the current BASE is DECIMAL) on\r
169 the output device.\r
170 \r
171         5 6 * .\r
172 \r
173 prints the product of 5 and 6 (30, base ten) on the output device.\r
174 \r
175         DECIMAL : CHARS 32 DO I . I EMIT CR LOOP ;\r
176         HEX 45 CHARS\r
177 \r
178 will set up a BIF "word" called CHARS, which, being invoked on the second\r
179 line, will print the characters and hexadecimal ascii codes from SPACE\r
180 up to, but not including, DASH.\r
181 \r
182 The BIF screens disk should always be in drive 0 if you want real error\r
183 messages.  If you want to look at the message text, the messages are at\r
184 the front of TOOLS.G00, after the directory screen and title screen.\r
185 Each message takes exactly 32 characters, including spaces and\r
186 non-printing characters.  Numbering starts with 0. If you have some\r
187 other disk in drive 0 you will get funny and not exactly intelligent\r
188 error messages.  I know it's weird, but I was following the fig-FORTH\r
189 model, which is designed for very limited memory.\r
190 \r
191 If you haven't been able to put the BIF screens disk together, you don't\r
192 really need it to play around with BIF, but do clear the WARNING\r
193 variable so BIF will know error messages are not available.  Aside from\r
194 the error messages in drive 0, there is nothing special about screens\r
195 disks, except they do not have directory tracks.  You should generally\r
196 not put them in your drives when running under BASIC (DECB), OS-9 or\r
197 some other system.  By tradition, programmers use the first several\r
198 screens as a hand-typed directory.  You can format fresh BIF disks with\r
199 either Disk Extended Color BASIC's DSKINI or OS-9's format.  BIF ignores\r
200 the directory information both systems write, so you also generally\r
201 should not put a real DECB or OS-9 disk in while BIF is running.\r
202 \r
203 If you do format with OS-9, format single-sided (I used DECB's disk\r
204 interface routines so BIF can't do double sided) with as many tracks as\r
205 you want.  To use the extra tracks, or a third or fourth drive, you will\r
206 need to modify the DRIVE-OFFSET array.  Pick a standard disk\r
207 configuration and stick with it.\r
208 \r
209 An important word of warning.  BIF, like FORTH, uses buffered I/O.  Your\r
210 screens are not actually saved to disk until you cause the system to\r
211 need enough new buffers to write your editing back to the disk.  To\r
212 force the system to save the buffers, give BIF the SAVE-BUFFERS command.\r
213 \r
214 \r
215 *******************************************************************************\r
216                            BIF's QUICK Editor\r
217 \r
218 \r
219 EDITOR          gets you into the EDITOR vocabulary.\r
220 0 QLIST         lets you look at the first sector of the directory.\r
221 4 B/SCR * QLIST lets you look at the first eight error messages.\r
222 DECIMAL         makes sure your conversion base is base ten.\r
223 64 B/SCR * QUICK\r
224                 lets you edit the first sector of the pairing example.\r
225                 Use the cursor keys to move around; use the BREAK key to\r
226                 get out.  If you modified something you don't want to\r
227                 change, type\r
228 EMPTY-BUFFERS   and ENTER.  If you want to make sure your changes are\r
229                 written to the disk, type\r
230 SAVE-BUFFERS    and ENTER.\r
231 \r
232 The QUICK editor is in the EDITOR vocabulary.  It is available at boot\r
233 up.  You'll need to get into the EDITOR vocabulary, to access it.  Pass\r
234 it a sector number, not a screen number.  Multiplying by B/SCR (which\r
235 happens to be 4) will convert a screen number to a sector number.  Add\r
236 1, 2, or 3 to the base sector number of a screen to get the sector\r
237 numbers for the second, third, and fourth sectors of that screen.\r
238 \r
239 The editor has no find/replace or block functions.  Again I apologize\r
240 for the editor, but I found it surprisingly workable.  Note that the\r
241 utility screens contain routines to move/copy sectors, so all is not\r
242 entirely mud.  One more glitch.  Lower case letters will show as VDG\r
243 codes until you run the cursor over them.  What can I say?\r
244 \r
245 During editing, all arrow keys are cursor controls.  Use SHIFT-LEFTARROW\r
246 for destructive backspace, SHIFT-DOWNARROW for `[' left bracket,\r
247 SHIFT-RIGHTARROW for `]' right bracket, SHIFT-UPARROW for `_' underscore\r
248 (back-arrow on CoCo2).  SHIFT-CLEAR escapes the UP-ARROW to provide the\r
249 `^' caret.  SHIFT-CLEAR also escapes itself to provide the backslash.\r
250 \r
251 Perhaps this is as good a place as any to mention a few points of\r
252 terminology.  A block is a sector.  Sectors are numbered sequentially\r
253 from 0.  Sector numbering continues sequentially from drive n to drive\r
254 n+1, see DRIVE-OFFSET, but also see OFFSET.  A SCREEN is a kilobyte\r
255 worth of blocks, in this case, four 256-byte sectors.  SCREEN numbering\r
256 also begins with 0.  (SCREENs are called SCREENs because a SCREEN can be\r
257 displayed on 16 lines of a 64-column CRT screen.)  You will notice that\r
258 a CoCo 2 can't properly display and edit a whole SCREEN.  Finally,\r
259 forward blocks are control constructs, not disk sectors.\r
260 \r
261 \r
262 *******************************************************************************\r
263                         The BIF Virtual Machine\r
264 \r
265 {       bifc_vm.h       ---\r
266 fig     6809\r
267 UP      [DP]    pointer to the per-USER variable table (USER Pointer)\r
268 IP      Y       pointer to the next definition (Instruction Pointer)\r
269 RP      S       return/control stack pointer\r
270 SP      U       parameter/data stack pointer\r
271 W       [S]     pointer to executing definition's parameter field\r
272 }\r
273                         The BIF Virtual Machine\r
274 \r
275 fig     6809\r
276 {       bifc_vm.c       bif.m   bifdp.a\r
277 NEXT    ( --- )         jmp [,y++] (macro in bif.m)\r
278         Causes the next definition to execute.\r
279 \r
280 DOCOL   ( *** IP )      jsr <XCOL (see bif.m, bifdp.a)\r
281         Characteristic of a colon (:) definition.  Begins execution of a\r
282         high-level definition, i. e., nests the definition and begins\r
283         processing icodes.  Mechanically, it pushes the IP (Y register)\r
284         and loads the Parameter Field Address of the definition which\r
285         called it into the IP.\r
286 }\r
287 {       symbol.c        bif.m   bifdp.a\r
288 DOVAR   ( --- vadr )    jsr <XVAR (bif.m, bifdp.a)\r
289         Characteristic of a VARIABLE.  A VARIABLE pushes its PFA address\r
290         on the stack.  The parameter field of a VARIABLE is the actual\r
291         allocation of the variable, so that pushing its address allows\r
292         its contents to be @ed (fetched).  Ordinary arrays and strings\r
293         that do not subscript themselves may be allocated by defining a\r
294         variable and immediately ALLOTting the remaining space.\r
295         VARIABLES are global to all users, and thus should have been\r
296         hidden in resource monitors, but aren't.\r
297 \r
298 DOCON   ( --- n )       jsr <XCON (bif.m, bifdp.a)\r
299         Characteristic of a CONSTANT.  A CONSTANT simply loads its value\r
300         from its parameter field and pushes it on the stack.\r
301 \r
302 DOUSER  ( --- vadr )    jsr <XUSER (bif.m, bifdp.a)\r
303         Characteristic of a per-USER variable. USER variables are\r
304         similiar to VARIABLEs, but are allocated (by hand!) in the\r
305         per-user table.  A USER variable's parameter field contains its\r
306         offset in the per-user table.\r
307 \r
308 DOVOC   ( --- )         jsr <XVOC (bif.m, bifdp.a)\r
309         Characteristic of a VOCABULARY.  A VOCABULARY stores a pointer\r
310         to itself in the current interpretation ROOT per-USER variable.\r
311         It contains a pointer to the definition at the root of its\r
312         symbol table tree.  This allows the symbol table routines to\r
313         treat the root as a leaf node.  This is also not standard FORTH!\r
314 \r
315         ( --- PFA )     ( *** IP )      jsr <XDOES (routine in bifdp.a)\r
316         Characteristic of a DOES> defined word.  The characteristics of\r
317         DOES> definitions are written in high-level icodes rather than\r
318         machine level code. The first parameter word points to the\r
319         high-level characteristic.  This routine's job is to push the\r
320         IP, load the high level characteristic pointer in IP, and leave\r
321         the address following the characteristic pointer on the stack so\r
322         the parameter field can be accessed.\r
323 \r
324 The following are not standard FORTH characteristics:\r
325 \r
326 DO1ARR  ( index --- eadr )      jsr <X1ARR (bif.m, bifdp.a)\r
327         Characteristic of a linear array. Linear arrays take the top\r
328         word on the stack as an index to the array, and return the\r
329         address of the element indexed.  So this routine subtracts the\r
330         base index of the array, limit checks the result, then\r
331         multiplies by the size of the array elements.  If the index is\r
332         out of bounds, it returns a NULL pointer (0).  At some point I\r
333         intended to implement multi-dimensional arrays in a similar\r
334         manner, but I haven't.  It would be a quick and interesting\r
335         project for anyone interested.\r
336 \r
337 DOUCON  ( --- n )       jsr <XUCON (bif.m, bifdp.a)\r
338         Characteristic of a USER variable treated as a CONSTANT, i. e.,\r
339         fetches the value stored at the specified offset in the per-user\r
340         table.\r
341 \r
342         ( --- d )       jsr <XDCON (bifdp.a)\r
343         Characteristic of a double integer constant; the parameter field\r
344         contains two words instead of one, both of which get pushed.\r
345 }\r
346 {       unused\r
347 ADDTOP  (MACRO in BIF.M) is not a characteristic; is used in several\r
348         routines to add a value to the top of stack.\r
349 }\r
350 \r
351 One of the primary problems with extending BIF is that calls to the\r
352 built-in characteristics are not conform to ;CODE.  Defining definitions\r
353 which use (;CODE) to establish the characteristics of the\r
354 sybmbols/definitions they define will hav a three-byte code field, where\r
355 the built-in compiling definitions -- VARIABLE, (1ARRAY, etc.,)\r
356 CONSTANT, USER, :, and VOCABULARY have two-byte code fields.  One\r
357 specific example of the difficulties this can create is that\r
358 vocabularies with special properties built in BIF, rather than by hand,\r
359 can't be searched by BIF's symbol table search routine, -FIND.  Of\r
360 course, XVOC could be moved to VOCABULARY, where it belongs, (and might\r
361 also be changed to a DOES> definition, but I don't think that's\r
362 necessary on the 6809).\r
363 \r
364 \r
365 *******************************************************************************\r
366                   The BIF Symbols/Definitions/Routines\r
367 \r
368 \r
369 I have added slightly to the FORTH documentation methods.  I also show\r
370 the results on the return stack and in the input buffer, where\r
371 appropriate.  The name on the left is the definition name, as it will be\r
372 found by ' (TICK) and the outer interpreter.  To the right I indicate\r
373 precedence (P for higher Precedence than definition) and restrictions (C\r
374 for Compile-only). Below the name, I indicate the assembler source\r
375 label, where it is different from the name.  The definitions on the\r
376 SCREENS disk also indicate screen and sector for the source.\r
377   \r
378 The parameters attempt to be mnemonic.  It will help to remember that\r
379 there are no stack items smaller than 16 bits; character and byte\r
380 parameters will be integers with their high-bytes ignored.  Double\r
381 integers are 32 bits.  A further reminder, parameters are listed Pascal\r
382 order, first pushed first; thus, the right-most is at the top of stack,\r
383 or the lowest address.  I specify a list of doubles pushed onto the\r
384 stack (used in the assembler) as dl. Finally, I will try to mean 16-bit\r
385 integer when I say word, but I may sometimes slip and mean (per FORTH\r
386 jargon) a definition/routine.\r
387 \r
388 Flags are slightly different than fig-FORTH -- true is set as -1, sensed\r
389 as non-zero.  False is zero, of course.\r
390 \r
391 A number of routines (such as ENCLOSE) accept and return different\r
392 parameters than specified in fig-FORTH.  I assume that those for whom\r
393 this fact may be of consequence will have copies of the standard and can\r
394 compare at their leisure.\r
395 \r
396 The definitions are not alphabetized, nor are they listed in order of\r
397 immediate interest, but they are organized by the source file they occur\r
398 in.  The following file descriptions are generally accurate, but some\r
399 code is out of place.\r
400 \r
401         BIF contains most of the virtual machine.\r
402 \r
403         BIF.M contains the inner interpreter macro, some important\r
404         symbol table offsets, and a few other general EQUates and\r
405         macros.\r
406 \r
407         BIFDP contains the rest of the virtual machine.\r
408 \r
409         BIFU contains the allocation of the per-user system variables.\r
410 \r
411         BIFST contains the boot up code and definitions.\r
412 \r
413         BIF1 contains most of the calculator-style expression evaluator.\r
414 \r
415         BIF2 is mostly constants and system variables, but contains the\r
416         memory management primitives.\r
417 \r
418         Most of BIF3 is code which interacts with system variables, for\r
419         example, the words which set the conversion base to sixteen,\r
420         ten, or eight.\r
421 \r
422         BIF4 contains multiplication and division, and the disk\r
423         interface primitives.\r
424 \r
425         BIF5 is mostly output formatting.\r
426 \r
427         BIF6 is mostly input formatting and terminal interface.\r
428 \r
429         BIF7 contains most of the dictionary (interactive symbol table)\r
430         machinery.\r
431 \r
432 Unless otherwise noted, all definitions are in the BIF vocabulary.\r
433 \r
434 There is much that is not sacred about FORTH and its dialects.  For\r
435 many, the attraction of FORTH is the great abandon with which one may\r
436 play games with its inner workings.  I have taken a number of liberties\r
437 and these routines still function.  If you have an idea, back your disks\r
438 up and try it.\r
439 \r
440 \r
441 ****          Definitions/Routines in BIF.ASM and BIFB.A:\r
442 {       vm_alu.c        bif.asm\r
443 @       ( adr --- n )\r
444 FETCH   Replace address on stack with the word at the address.\r
445 \r
446 \r
447 !       ( n adr --- )\r
448 STORE   Store second word on stack at address on top of stack.\r
449 \r
450 LIT     ( --- n )                                               C\r
451         Push the following word from the instruction stream as a\r
452         literal, or immediate value.\r
453 \r
454 DLIT    ( --- d )                                               C\r
455         Push a double integer literal (see LIT).\r
456 }\r
457 \r
458 {       bifc_vm.c       bif.asm\r
459 EXECUTE ( adr --- )                                             C\r
460 EXEC    Jump to address on stack.  Used by the "outer" interpreter to\r
461         interactively invoke routines.  (Not compile-only in fig.)\r
462 \r
463 0BRANCH ( f --- )                                               C\r
464 ZBR     BRANCH if flag is zero.\r
465 \r
466 1BRANCH ( f --- )                                               C\r
467 TBR     BRANCH if not zero.  Not as useful as it might appear.\r
468 \r
469 BRANCH  ( --- )                                                 C\r
470         Add the following word from the instruction stream to the\r
471         instruction pointer (Y++).  Causes a program branch.\r
472 }\r
473 \r
474 (LOOP)  ( --- )         ( limit index *** limit index+1)        C\r
475 XLOOP                   ( limit index *** )\r
476         Counting loop primitive.  The counter and limit are the top two\r
477         words on the return stack.  If the updated index/counter does\r
478         not exceed the limit, a branch occurs.  If it does, the branch\r
479         does not occur, and the index and limit are dropped from the\r
480         return stack.\r
481 \r
482 (+LOOP) ( n --- )       ( limit index *** limit index+n )       C\r
483 XPLOOP                  ( limit index *** )\r
484         Loop with a variable increment.  Terminates when the index\r
485         crosses the boundary from one below the limit to the limit.  A\r
486         positive n will cause termination if the result index equals the\r
487         limit.  A negative n must cause the index to become less than\r
488         the limit to cause loop termination.\r
489 \r
490 (DO)    ( limit index --- )     ( *** limit index )\r
491 XDO     Move the loop parameters to the return stack.  Synonym for D>R.\r
492 \r
493 I       ( --- index )           ( limit index *** limit index )\r
494         Copy the loop index from the return stack.  Synonym for R.\r
495 \r
496 J       ( --- index2 )  ( index2 limit1 index1 *** index2 limit1 index1 )\r
497         Copy the outer loop index from the return stack.  As with (DO)\r
498         and I, J may be useful outside looping contexts.\r
499 \r
500 DIGIT   ( c base --- ff )\r
501         ( c base --- n tf )\r
502         Translate C in base, yielding a translation valid flag.  If the\r
503         translation is not valid in the specified base, only the false\r
504         flag is returned.\r
505 \r
506 (FIND)  ( name vocptr --- locptr f )\r
507 PFIND   Search vocabulary for a symbol called name.  Name is a pointer\r
508         to a NUL terminated string of characters without count, vocptr\r
509         is a pointer to a pointer to a definition (the length byte of a\r
510         symbol table entry).  Locptr is also a pointer to a pointer to a\r
511         definition, such that, if the flag is false, a symbol with the\r
512         name searched for may be inserted in proper order at that point.\r
513         Vocptr and locptr may point to either the right or left entry of\r
514         the order-parent entry in the symbol table, or to pointer to the\r
515         root of a vocabulary.  HIDDEN (smudged) definitions are\r
516         lexically less than their name strings.  Searches only the local\r
517         vocabulary, from the order-parent node passed.  Uses (REFIND).\r
518 \r
519                 vocptr is a pointer to the parameter field of a vocabulary \r
520                 header.\r
521 \r
522 ENCLOSE ( buffer c --- s length )\r
523 ENCLOS  Scan buffer for a symbol delimited by c or ASCII NUL; return the\r
524         length of the symbol scanned and the address of its first\r
525         character.  A length 0 and a pointer to a NUL means no symbol\r
526         was scanned before NUL terminator was reached.  (Buffer is the\r
527         address of the buffer array to scan.)\r
528 \r
529 LITERAL ( n --- )                                               P\r
530 LITER   ( n --- n ) if interpreting.\r
531         Compile n as a literal, if compiling.\r
532 \r
533 DLITERAL        ( d --- )                                       P\r
534 DLITER          ( d --- d ) if interpreting.\r
535         Compile d as a double literal, if compiling.\r
536 \r
537 EMIT    ( c --- )\r
538         Write c to the output device (screen or printer).  Uses the ECB\r
539         device number at address $6F, -2 is printer, 0 is screen.\r
540 \r
541 KEY     ( --- c )\r
542         ( --- BREAK )\r
543         Wait for a key from the keyboard.  If the key is BREAK, set the\r
544         high byte (result $FF03).\r
545 \r
546 ?TERMINAL       ( --- f )\r
547 QTERM   Scan keyboard, but do not wait.  Return 0 if no key, BREAK\r
548         ($ff03) if BREAK is pressed, or key currently pressed.\r
549 \r
550 CR      ( --- )\r
551         EMIT a Carriage Return (ASCII CR).\r
552 \r
553 (;CODE) ( --- )         ( IP *** )                              C\r
554 XSCODE  Compile the latest symbol as a reference to a ;CODE definition;\r
555         overwrite the first three (3!) bytes of the code field of the\r
556         symbol found by LATEST with a jump to the low-level\r
557         characteristic code provided in the defining definition, and pop\r
558         IP.  The machine-level code which follows (;CODE) in the\r
559         instruction stream is not executed by the defining symbol, but\r
560         becomes the characteristic of the defined symbol.  This is the\r
561         usual way to generate the characteristics of VARIABLEs,\r
562         CONSTANTs, etc., when FORTH compiles itself.  BIF, however, was\r
563         hand-optimized to take advantage of direct-page jumps.  So its\r
564         pre-compiled defining symbols with low-level characteristics\r
565         look different from those compiled by BIF, having two bytes in\r
566         their code fields instead of three.\r
567 \r
568 >PRT    ( --- )\r
569 TOPRT   Send output to printer via CoCo's ROM routines and the device\r
570         number variable (see EMIT).\r
571 \r
572 >VID    ( --- )\r
573 TOVID   Send output to CRT, converse of >PRT.\r
574 \r
575 2*      ( n --- n*2 )\r
576 LSHIFT  Fast multiply by two.\r
577 \r
578 2/      ( n --- n/2 )\r
579 RSHIFT  Fast divide by two.\r
580 \r
581 (REFIND)        ( name vocptr --- name locptr f )\r
582 PREF    Search vocabulary for the first symbol called name.  (Will find\r
583         HIDDEN/SMUDGEd definitions.)  Name is a pointer to a string of\r
584         characters without count, vocptr is a pointer to a pointer to a\r
585         definition (the length byte of a symbol table entry).  Locptr is\r
586         also a pointer to a pointer to a definition, such that, if the\r
587         pointer at the pointer is NULL, a symbol with the name searched\r
588         for may be inserted in proper order at that point.  Vocptr and\r
589         locptr may be either the right or left entry of the order-parent\r
590         entry in the symbol table, or a pointer to the root of a\r
591         vocabulary.  Flag f will indicate by offset whether the child or\r
592         empty slot is a left link (LFTOFF), right link (RTOFF), or\r
593         vocabulary (PFAOFF).\r
594 \r
595                 vocptr is a pointer to the parameter field of a vocabulary \r
596                 header.\r
597 \r
598 \r
599 ****          Definitions/Routines in BIF1.A and BIF1B.A:\r
600 \r
601 MOVE    ( source target count --- )\r
602         Copy/move count words from source to target.  Moves ascending\r
603         addresses, so that overlapping only works if the source is\r
604         above the destination.\r
605 \r
606 CMOVE   ( source target count --- )\r
607         Copy/move count bytes from source to target.  Moves ascending\r
608         addresses, so that overlapping only works if the source is\r
609         above the destination.\r
610 \r
611 U*      ( u1 u2 --- ud )\r
612 USTAR   Multiplies the top two unsigned integers, yielding a double\r
613         integer product.\r
614 \r
615 U/      ( ud u --- uremainder uquotient )\r
616 USLASH  Divides the top unsigned integer into the second and third words\r
617         on the stack as a single unsigned double integer, leaving the\r
618         remainder and quotient (quotient on top) as unsigned integers.\r
619                 \r
620                 The smaller the divisor, the more likely dropping the high word \r
621                 of the quotient loses significant bits.\r
622 \r
623 AND     ( n1 n2 --- n )\r
624         Bitwise and the top two integers.\r
625 \r
626 OR      ( n1 n2 --- n )\r
627         Bitwise or.\r
628 \r
629 XOR     ( n1 n2 --- n )\r
630         Bitwise exclusive or.\r
631 \r
632 SP@     ( --- adr )\r
633 SPFEH   Fetch the parameter stack pointer (before it is pushed).\r
634 \r
635 SP!     ( whatever --- nothing )\r
636 SPSTO   Initialize the parameter stack pointer from the USER variable\r
637         S0.  Effectively clears the stack.\r
638 \r
639 RP!     ( whatever *** nothing )\r
640 RPSTO   Initialize the return stack pointer from the USER variable R0.\r
641         Effectively aborts all in process definitions, except the active\r
642         one.  An emergency measure, to be sure.\r
643 \r
644 ;S      ( ip *** )\r
645 SEMIS   Pop IP from return stack (return from high-level definition).\r
646         Can be used in a screen to force interpretion to terminate.\r
647 \r
648 LEAVE   ( limit index *** index index )\r
649         Force the terminating condition for the innermost loop by\r
650         copying its index to its limit.  Termination is postponed until\r
651         the next LOOP or +LOOP instruction is executed.  The index\r
652         remains available for use until the LOOP or +LOOP instruction is\r
653         encountered.\r
654 \r
655 >R      ( n --- )               ( *** n )                       C\r
656 TOR     Move top of parameter stack to top of return stack.\r
657 \r
658 R>      ( --- n )               (n *** )                        C\r
659 RFROM   Move top of return stack to top of parameter stack.\r
660 \r
661 R       ( --- n )               ( n *** n )\r
662         Copy the top of return stack to top of parameter stack.  A\r
663         synonym for I.\r
664 \r
665 =       ( n1 n2 --- n1=n2 )\r
666 EQ      Flag true if n1 and n2 are equal, otherwise false.\r
667 \r
668 <       ( n1 n2 --- n1<n2 )\r
669 LT      Flag true if n1 is less than n2, otherwise false.\r
670 \r
671 0=      ( n --- n=0 )\r
672 ZEQ     Logically invert top of stack; or flag true if top is zero,\r
673         otherwise false.\r
674 \r
675 0<      ( n --- n<0 )\r
676 ZLESS   Flag true if top is negative (MSbit set), otherwise false.\r
677 \r
678 >       ( n1 n2 --- n1>n2 )\r
679 GT      Flag true if n1 is greater than n2, false otherwise.\r
680 \r
681 {       vm_alu.c        bif1.a\r
682 +       ( n1 n2 --- n1+n2 )\r
683 ADD     Add top two words.\r
684 \r
685 -       ( n1 n2 --- n1-n2 )\r
686 SUB     Subtract top two words.\r
687 }\r
688 \r
689 D+      ( d1 d2 --- d1+d2 )\r
690 DADD    Add top two double integers.\r
691 \r
692 D-      ( d1 d2 --- d1-d2 )\r
693 DSUB    Subtract top two double integers.\r
694 \r
695 MINUS   ( n --- -n )\r
696         Negate (two's complement) top of stack.\r
697 \r
698 DMINUS  ( d --- -d )\r
699         Negate (two's complement) top two words on stack as a double\r
700         integer.\r
701 \r
702 OVER    ( n1 n2 --- n1 n2 n1 )\r
703         Push a copy of the second word on stack.\r
704 \r
705 DROP    ( n --- )\r
706         Discard the top word on stack.\r
707 \r
708 SWAP    ( n1 n2 --- n2 n1 )\r
709         Swap the top two words on stack.\r
710 \r
711 DUP     ( n1 --- n1 n1 )\r
712         Push a copy of the top word on stack.\r
713 \r
714 +!      ( n adr --- )\r
715 ADDSTO  Add the second word on stack to the word at the adr on top of\r
716         stack.\r
717 \r
718 TOGGLE  ( adr b --- )\r
719 TOG     Exclusive or byte at adr with low byte of top word.\r
720 \r
721 C@      ( adr --- b )\r
722 CFEH    Replace address on top of stack with the byte at the address.\r
723         High byte of result is clear.\r
724 \r
725 C!      ( b adr --- )\r
726 CSTO    Store low byte of second word on stack at address on top of\r
727         stack.  High byte is ignored.\r
728 \r
729 ROT     ( n1 n2 n3 --- n2 n3 n1 )\r
730         Rotate the top three words on stack, bringing the third word to\r
731         the top.\r
732 \r
733 BACK    ( adr --- )                                             C\r
734         Calculate a back reference from HERE and compile it.  The result\r
735         compiled is adr-HERE-2, being adjusted for post-increment\r
736         addressing.\r
737 \r
738 NOT     ( n --- ~n )\r
739         Bit (one's) complement the top of stack.\r
740 \r
741 '       ( --- ) compiling                                       P\r
742 TICK    ( --- adr ) interpreting\r
743         { ' name } input\r
744         Parse a symbol name from input and search, -DFIND, the\r
745         dictionary for it; compile the address as a literal if\r
746         compiling, otherwise just push it.  Recursively searches parent\r
747         vocabularies, aborts if the parsed symbol name is not found.\r
748 \r
749 -->     ( --- )                                                 P\r
750 NEXSCR  Continue interpreting source code on the next screen.\r
751 \r
752 1ARRAY  ( start end size --- )\r
753 ONEARR  { 1ARRAY name } input\r
754         Parse name and compile it as a linear array of size elements\r
755         from start index to end index inclusive.  The number of bytes in\r
756         the array is (end-start+1)*size.  The 1ARRAY characteristic is a\r
757         direct page routine.\r
758 \r
759 UTILITIES       ( --- )\r
760 UTIL    The UTILITIES vocabulary.\r
761 \r
762 DP@     ( --- adr )                             in UTILITIES\r
763 DPFEH   Calculate and push the address of the direct page.\r
764 \r
765 DCONSTANT       ( d --- )\r
766 DCON    { DCONSTANT name } input\r
767         Parse name and compile it as a double constant with a value of\r
768         d.  The DCONSTANT characteristic is a direct page routine.\r
769 \r
770 SWAB    ( n --- ns )\r
771         Swap the bytes of the top word on stack.\r
772 \r
773 SWAN    ( n --- ns )\r
774         Swap the nibbles of the top word on stack.  The low-level code\r
775         looks funny, but it was the fastest way I could think up.\r
776 \r
777 \r
778 ****          Definitions/Routines in BIF2.A and BIF2B.A:\r
779 \r
780 Increments and decrements for top of stack:\r
781 1+      ADD1    ( n --- n+1 )\r
782 1-      SUB1    ( n --- n-1 )\r
783 2+      ADD2    ( n --- n+2 )\r
784 2-      SUB2    ( n --- n-2 )\r
785 \r
786 Constants:\r
787 0       ZERO    ( --- 0 )\r
788 1       ONE     ( --- 1 )\r
789 -1      MONE    ( --- -1 )\r
790 2       TWO     ( --- 2 )\r
791 3       THREE   ( --- 3 )\r
792 BL      BL      ( --- SP )      ASCII SPACE character\r
793 C/L     CPERL   ( --- 32 )      The number of columns per line on the\r
794                 CRT.  Determines the length of error messages and the\r
795                 width and length of screen listings, among other things.\r
796 FIRST           ( --- adr )     The base of the disk buffer space.\r
797 LIMIT           ( --- adr )     The limit of the disk buffer space.\r
798 B/BUF   BPBUF   ( --- 256 )     The size, in bytes, of a buffer.\r
799 B/SCR   BPSCR   ( --- 4 )       The size, in buffers, of a screen.\r
800 \r
801 +ORIGIN ( n --- adr )\r
802 PORIG   Calculate the address of the (n/2)th entry in the boot-up\r
803         parameter table.  (Adds the base of the boot-up table to n.)\r
804 \r
805 Variables:\r
806 TIB             ( --- vadr )    Terminal Input Buffer address.  Note\r
807                 that is a variable, so users may allocate their own\r
808                 buffers, but it must be @ed.\r
809 WARNING WARN    ( --- vadr )    Availability of error messages on disk.\r
810                 Contains 1 if messages available, 0 if not, -1 if a disk\r
811                 error has occurred.\r
812                                 In bif-c, add 2 for internal error strings.\r
813 FENCE           ( --- vadr )    Boundary for FORGET.\r
814 DP      DPC     ( --- vadr )    Dictionary pointer, fetched by HERE.\r
815 ROOT            ( --- vadr )    Current local/context interpretation\r
816                 vocabulary root.  Not a fig variable.\r
817 BLK             ( --- vadr )    Block being interpreted.  Zero refers to\r
818                 terminal.\r
819 IN              ( --- vadr )    Input buffer offset/cursor.\r
820 OUT             ( --- vadr )    Output buffer offset/cursor.\r
821 SCR             ( --- vadr )    Screen being edited.  Unused in BIF.\r
822 OFFSET          ( --- vadr )    Sector offset for LOADing screens, set\r
823                 by DRIVE to make a new drive the default.\r
824 STATE           ( --- vadr )    Compiler/interpreter state.\r
825 BASE            ( --- vadr )    Numeric conversion base.\r
826 DPL             ( --- vadr )    Output decimal point locator.\r
827 FLD             ( --- vadr )    Field width for I/O formatting.\r
828 CSP             ( --- vadr )    Compiler stack mark for stack check.\r
829 R#      RNUM    ( --- vadr )    Editing cursor location.  Unused in BIF.\r
830 HLD             ( --- vadr )    Pointer to last HELD character in PAD.\r
831 FOREWARD FORE   ( --- vadr )    Pointer to earliest definition in active\r
832                 forward block. Not fig.\r
833 CURRENT CURR    ( --- vadr )    NFA of LATEST definition.  Not fig.\r
834 PREV            ( --- vadr )    Most Recently Used buffer.\r
835 USE             ( --- vadr )    Least Recently Used buffer.\r
836 DROOT           ( --- vadr )    Current defining/compiling vocabulary\r
837                 root.  Not fig.\r
838 \r
839 HERE    ( --- adr )\r
840         Get contents of DP, with heap/stack overflow ERROR check.  More\r
841         than a pseudo-constant.\r
842 \r
843 ALLOT   ( n --- )\r
844         Increase heap (add n to DP), ERROR check stack/heap.\r
845 \r
846 ,       ( n --- )\r
847 COMMA   Store word n at DP++, ERROR check stack/heap.\r
848 \r
849 C,      ( b --- )\r
850 CCOMMA  Store byte b at DP+, ERROR check stack/heap.\r
851 \r
852 SPACE   ( --- )\r
853         EMIT a SPACE.\r
854 \r
855 -DUP    ( 0 --- 0 )\r
856 DDUP    ( n --- n n )\r
857         DUP if non-zero.\r
858 \r
859 ?CST    ( --- f )\r
860 QCST    Push compile/interpret state bits.\r
861 \r
862 IF      ( --- cdptr $4946 )                                     P,C\r
863         Compile a 0BRANCH and dummy offset and push IF reference to fill\r
864         in and IF control construct flag.\r
865 \r
866 ELSE    ( cdptr1 $4946 --- cdptr2 $4946 )                       P,C\r
867         ERROR check IF flag, compile BRANCH with dummy offset, resolve\r
868         IF reference (FILL-IN offset-2 to HERE at cdptr1), and leave\r
869         reference to BRANCH for ELSE.\r
870 \r
871 \r
872 ENDIF   ( cdptr $4946 --- )                                     P,C\r
873         ERROR check IF flag, resolve IF reference (FILL-IN offset-2 to\r
874         HERE at cdptr) and pop reference/flag.\r
875 \r
876 \r
877 ****          Definitions/Routines in BIF3.A and BIF3B.A:\r
878 \r
879 LATEST  ( --- symptr )\r
880         Fetch CURRENT as a per-USER constant.\r
881 \r
882 Symbol table conversions:\r
883 LFA     ( n --- n+LFAOFF )      Convert NFA (not PFA) to LFA.\r
884         --> Convert header address to LFA.\r
885 CFA     ( n --- n+CFAOFF )      Convert NFA (not PFA) to CFA.\r
886         --> Convert header address to CFA.\r
887 GFA     ( n --- n+GFAOFF )      Convert NFA (not PFA) to CFA.\r
888         --> Convert header address to GFA.\r
889 PFA     ( n --- n+PFAOFF )      Convert NFA to PFA.\r
890         --> Convert header address to PFA.\r
891 NFA     ( n --- n-PFAOFF )      Convert PFA to NFA.\r
892         --> Convert PFA to header address.\r
893         NFA is the address of the length byte in a symbol table header.\r
894         --> Now we use the header address instead of the NFA.\r
895         PFA is the address at which a high-level definition's icode list\r
896         begins, or a variable's, constant's, or vocabulary's value is\r
897         stored.\r
898         CFA is where a definition's code begins, or where the jump to\r
899         its characteristic is stored.\r
900         LFA is the address of a definition's allocation link.\r
901         GFA is the address of a definition's vocabulary link.\r
902 \r
903 !CSP    ( --- )\r
904 STOCSP  Save the parameter stack pointer in CSP for compiler checks.\r
905 \r
906 Set the conversion base:\r
907 HEX             ( --- )         Sixteen.\r
908 DECIMAL DEC     ( --- )         Ten.\r
909 OCTAL   OCT     ( --- )         Eight.\r
910 \r
911 FILL    ( adr n b --- )\r
912         Fill n bytes at adr with b.\r
913 \r
914 ERASE   ( adr n --- )\r
915         Fill n bytes with 0.\r
916 \r
917 BLANKS  ( adr n --- )\r
918         Fill n bytes with ASCII SPACE.\r
919 \r
920 HOLD    ( c --- )\r
921         Format a character at the left of the HLD output buffer.\r
922 \r
923 PAD     ( --- adr )\r
924         Give the address of the output PAD buffer.  Not same as fig. PAD\r
925         points to the end of a 34 byte buffer for numeric conversion.\r
926 \r
927 S->D    ( n0 --- d0 )\r
928 STOD    Sign extend n0 to a double integer.\r
929 \r
930 +-      ( n0 n1>=0 --- n0 )\r
931 CHS     ( n0 n1<0 --- -n0 )\r
932         Change sign of second iff top is negative.\r
933 \r
934 D+-     ( d0 n0>=0 --- d0 )\r
935 DCHS    ( d0 n0<0 --- -d0 )\r
936         Change sign of second and third as double iff top is negative.\r
937 \r
938 ABS     ( n>=0 --- n )\r
939         ( n<0 --- -n )\r
940         Change the top of stack to its absolute value.\r
941 \r
942 DABS    ( d>=0 --- d )\r
943         ( d<0 --- -d )\r
944         Change the top double to its absolute value.\r
945 \r
946 MIN     ( n0 n1 --- min(n0,n1) )\r
947         Leave the minimum of the top two integers.\r
948 \r
949 MAX     ( n0 n1 --- max(n0,n1) )\r
950         Leave the maximum of the top two integers.\r
951 \r
952 [       ( --- )                                                 P\r
953 LBRAK   Clear the compile state bits (shift to interpret).\r
954 \r
955 ]       ( --- )\r
956 RBRAK   Set the compile state bits (shift to compile).\r
957 \r
958 IMMEDIATE       ( --- )\r
959 IMMED   Toggle precedence bit of LATEST definition header.  During\r
960         compiling, most symbols scanned are compiled.  IMMEDIATE\r
961         definitions execute whenever the outer INTERPRETer scans them,\r
962         but may be compiled via ' (TICK).\r
963 \r
964 SMUDGE  ( --- )\r
965         Toggle HIDDEN bit of LATEST definition header, to hide it until\r
966         defined or reveal it after definition.\r
967 \r
968 COMPILE-ONLY    ( --- )\r
969 COMPO   Toggle compile only bit of LATEST definition header.\r
970 \r
971 COUNT   ( strptr --- strptr+1 count )\r
972         Convert counted string to string and count.  (Fetch the byte at\r
973         strptr, post-increment.)\r
974 \r
975 -TRAILING       ( strptr count1 --- strptr count2 )\r
976 DTRAIL  Supress trailing blanks (subtract count of trailing blanks from\r
977         strptr).\r
978 \r
979 (MACHINE)       ( ip *** )                                      C\r
980 XMACH   Change from executing icodes to machine code in a definition by\r
981         saving IP and jumping to it after popping the old IP.\r
982 \r
983 TYPE    ( strptr count --- )\r
984         EMIT count characters at strptr.\r
985 \r
986 CTS-TYPE     ( adr --- )                             in UTILITIES (bif-c)\r
987 CTD_TYPE   TYPE the (byte) counted string at adr.\r
988 \r
989 (.")    ( --- )                                                 C\r
990 XDOTQ   TYPE counted string out of instruction stream (updating IP).\r
991 \r
992 ID.     ( symptr --- )\r
993 IDDOT   Print definition's name from its NFA.\r
994 \r
995 FILL-IN ( cdptr --- )                                           C\r
996 FILLIN  Resolve the reference at cdptr by writing the offset from\r
997         cdptr+2 to HERE at cdptr.  Offset is adjusted for post-increment\r
998         IP (ldd ,y++).\r
999 \r
1000 BEGIN   ( --- cdptr $4245 )                                     P,C\r
1001         Push HERE for BACK reference for general (non-counting) loops,\r
1002         with BEGIN construct flag.\r
1003 \r
1004 AGAIN   ( cdptr $4245 --- )                                     P,C\r
1005         ERROR check BEGIN flag, compile BRANCH and BACK resolve it to\r
1006         cdptr.\r
1007 \r
1008 UNTIL   ( cdptr $4245 --- )                                     P,C\r
1009         ERROR check BEGIN flag, compile 0BRANCH and BACK resolve it to\r
1010         cdptr.\r
1011 \r
1012 WHILE   ( $4245 --- $4245 cdptr $5748 )                         P,C\r
1013         ERROR check BEGIN flag, compile 0BRANCH with dummy offset, push\r
1014         WHILE reference -- HERE -- /flag on top of BEGIN reference/flag.\r
1015 \r
1016 REPEAT  ( cdptr1 $4245 cdptr2 $5748 --- )                       P,C\r
1017         ERROR check WHILE and BEGIN flags, compile BRANCH and BACK fill\r
1018         cdptr1 reference, FILL-IN 0BRANCH reference at cdptr2.\r
1019 \r
1020 DO      ( --- cdptr $444F )                                     P,C\r
1021         Compile (DO), push HERE for BACK refenece, and push DO control\r
1022         construct flag.\r
1023 \r
1024 \r
1025 ****          Definitions/Routines in BIF4.A and BIF4B.A:\r
1026 \r
1027 M*      ( n1 n2 --- d )\r
1028 MSTAR   Multiply top two words as signed integers with a signed double\r
1029         result.\r
1030 \r
1031 M/      ( d n --- remainder quotient )\r
1032 MSLASH  Divide signed double dividend d (2nd & 3rd words) by signed\r
1033         word divisor n (top) yielding signed word remainder and quotient.\r
1034         Quotient is top, remainder takes sign of dividend.\r
1035                 \r
1036                 Thus, dividend == quotient * divisor + remainder \r
1037                 with truncating toward zero.\r
1038                 This can overflow in quotient.\r
1039 \r
1040 *       ( multiplier multiplicand --- product )\r
1041 STAR    Signed word multiply.\r
1042 \r
1043 /MOD    ( dividend divisor --- remainder quotient )\r
1044 SLAMOD  M/ in word-only form, i. e., signed division of 2nd word by top\r
1045         word yielding signed word quotient and remainder.\r
1046 \r
1047 /       ( dividend divisor --- quotient )\r
1048 SLASH   Signed word divide without remainder.\r
1049 \r
1050 MOD     ( dividend divisor --- remainder )\r
1051         Remainder function, result takes sign of dividend.\r
1052 \r
1053 */MOD   ( multiplier multiplicand divisor --- remainder quotient )\r
1054 SSMOD   Signed precise division of product: multiply 2nd and 3rd\r
1055         words on stack and divide the 31-bit product by the top word,\r
1056         leaving both quotient and remainder.  Remainder takes sign of\r
1057         product.  Guaranteed not to lose significant bits.\r
1058 \r
1059 */      ( multiplier multiplicand divisor --- quotient )\r
1060 STARSL  */MOD without remainder.\r
1061 \r
1062 M/MOD   ( ud1 u1 --- u2 ud2 )\r
1063 MSMOD   U/ with an (unsigned) double quotient.  Guaranteed not to lose\r
1064         significant bits, if you are prepared to deal with them.\r
1065 \r
1066 +BUF    ( buffer1 --- buffer2 f )\r
1067 ADDBUF  Bump to next buffer, flag false if result is PREVious buffer,\r
1068         otherwise flag true.  Used in the LRU allocation routines.\r
1069 \r
1070 UPDATE  ( --- )\r
1071         Mark PREVious buffer dirty, in need of being written out.\r
1072 \r
1073 EMPTY-BUFFERS   ( --- )\r
1074 EMTBUF  Mark all buffers empty.  Standard method of discarding changes.\r
1075 \r
1076 DRIVE-OFFSET    ( n --- eadr )\r
1077 DROFFS  1ARRAY of drive offsets (see DO1ARR in the description of the\r
1078         virtual machine).  Contains the size, in sectors, of four\r
1079         drives, plus a fifth entry to end the table if all four drives\r
1080         are defined.  To make drive 2 a 40 track SS-DD drive:\r
1081                 40 18 * 2 DRIVE-OFFSET !\r
1082         (Formatting the extra tracks can be handled with OS-9.)\r
1083 \r
1084 DRIVE   ( n --- )\r
1085         Add up the sector offset to sector 0 of drive n and store it in\r
1086         OFFSET.  This changes the logically lowest drive for LOADING.\r
1087 \r
1088 R/W     ( buffer sector f --- )\r
1089 RW      Read or Write the specified (absolute -- ignores OFFSET) sector\r
1090         from or to the specified buffer.  A zero flag specifies write,\r
1091         non-zero specifies read.  Sector is an unsigned integer, buffer\r
1092         is the buffer's address.  Uses the CoCo ROM disk routines.  This\r
1093         is where you would want to handle double-sided drives.\r
1094 \r
1095 ?ERROR  ( 0 n --- )             ( *** )\r
1096 QERROR  ( true n --- IN BLK )   ( anything *** nothing )\r
1097         If flag is false, do nothing.  If flag is true, issue error\r
1098         MESSAGE and QUIT or ABORT, via ERROR.  Leaves cursor position\r
1099         (IN) and currently loading block number (BLK) on stack, for\r
1100         analysis.\r
1101 \r
1102 ?COMP   ( --- )                 ( *** )\r
1103 QCOMP   ( --- IN BLK )          ( anything *** nothing )\r
1104         ERROR if not compiling.\r
1105 \r
1106 ?EXEC   ( --- )                 ( *** )\r
1107 QEXEC   ( --- IN BLK )          ( anything *** nothing )\r
1108         ERROR if not executing.\r
1109 \r
1110 ?PAIRS  ( n1 n2 --- )           ( *** )\r
1111 QPAIRS  ( n1 n2 --- IN BLK )    ( anything *** nothing )\r
1112         ERROR if n1 and n2 are unequal.  MESSAGE says compiled\r
1113         conditionals do not match.\r
1114 \r
1115 ?CSP    ( --- )                 ( *** )\r
1116 QCSP    ( --- IN BLK )          ( anything *** nothing )\r
1117         ERROR if return/control stack is not at same level as last !CSP.\r
1118         Used to indicate that a definition has been left incomplete.\r
1119                 *** Actually, this checks the parameter stack. ***\r
1120 \r
1121 ?LOADING        ( --- )         ( *** )\r
1122 QLOAD   ( --- IN BLK )          ( anything *** nothing )\r
1123         ERROR if not loading, i. e., if BLK is non-zero. [correction: if BLK _is_ zero!]\r
1124 \r
1125 COMPILE ( --- )\r
1126 COMP    Compile an in-line literal value from the instruction stream.\r
1127 \r
1128 LOOP    ( cdptr $444f --- )                                     P,C\r
1129         ERROR check DO flag, compile (LOOP), fill in BACK reference.\r
1130 \r
1131 +LOOP   ( cdptr $444f --- )                                     P,C\r
1132 PLOOP   ERROR check DO flag, compile (+LOOP), fill in BACK reference.\r
1133 \r
1134 LOAD    ( n --- )\r
1135         Begin interpretation of screen (block) n.  See also NEXSRC,\r
1136         SEMIS, and ***NULLL****GGGGGHHHHTHNiTHNiTHNi\r
1137 \r
1138 <BUILDS ( --- )                                                 C\r
1139 BUILDS  Build a header for DOES> definitions.  Actually just compiles a\r
1140         CONSTANT zero which can be overwritten later by DOES>.  Note\r
1141         that <BUILDS is not IMMEDIATE, and therefore executes during a\r
1142         definition's run-time, rather than its compile-time.  It is not\r
1143         intended to be used directly, but rather so that one definition\r
1144         can build another.  Also, note that nothing particularly special\r
1145         happens in the defining definition until DOES> executes.  The\r
1146         name <BUILDS is intended to be a reminder of what is about to\r
1147         occur.\r
1148 \r
1149 DOES>   ( --- )         ( IP *** )                              C\r
1150 DOES    Define run-time behavior of definitions compiled/defined by a\r
1151         high-level defining definition -- the FORTH equivalent of a\r
1152         compiler-compiler.  DOES> assumes that the LATEST symbol table\r
1153         entry has at least one word of parameter field, which <BUILDS\r
1154         provides.  Note that DOES> is also not IMMEDIATE.  When the\r
1155         defining word containing DOES> executes the DOES> icode, it\r
1156         overwrites the LATEST symbol's CFA with jsr <XDOES, overwrites\r
1157         the first word of that symbol's parameter field with its own IP,\r
1158         and pops the previous IP from the return stack. The icodes which\r
1159         follow DOES> in the stream do not execute at the defining word's\r
1160         run-time. Examining XDOES in the virtual machine shows that the\r
1161         defined word will execute those icodes which follow DOES> at its\r
1162         own run-time.  The advantage of this kind of behaviour, which\r
1163         you will also note in ;CODE, is that the defined word can\r
1164         contain both operations and data to be operated on.  This is how\r
1165         FORTH data objects define their own behavior.  Finally, note\r
1166         that the effective code field for DOES> definitions is four\r
1167         bytes.\r
1168 \r
1169 ;CODE   ( --- )                                                 P,C\r
1170 SCODE   ?CSP to see if there are loose ends in the defining definition\r
1171         before shifting to the assembler, compile (;CODE) in\r
1172         the defining definition's instruction stream, shift to\r
1173         interpreting, make the ASSEMBLER vocabulary current, and !CSP to\r
1174         mark the stack in preparation for assembling low-level code.\r
1175         Note that ;CODE, unlike DOES>, is IMMEDIATE, and compiles\r
1176         (;CODE),which will do the actual work of changing the LATEST\r
1177         definition's characteristic when the defining word runs.\r
1178         Assembly is done by the interpreter, rather than the compiler.\r
1179         I could have avoided the anomalous three-byte code fields by\r
1180         having ;CODE compile in the direct page jumps to the actual\r
1181         low-level characteristics in the defining definition, thus\r
1182         allowing (;CODE) to write a two-byte direct-page jumps into the\r
1183         code fields of defined words.  But that's a lot of work!\r
1184 \r
1185 \r
1186 ****          Definitions/Routines in BIF5.A and BIF5B.A:\r
1187 \r
1188 \r
1189 IP,     ( --- )                                                 C\r
1190 IPCOM   COMPILE a literal out of the instruction stream, without\r
1191         checking compiler state.  Used by the assembler to stuff\r
1192         op-codes into the instruction stream, since the assembler runs\r
1193         in interpretation mode.\r
1194 \r
1195 ?STACK  ( --- )                 ( *** )\r
1196 QSTACK  ( --- IN BLK )          ( anything *** nothing )\r
1197         ERROR if either stack out of bounds, or on evidence of stack\r
1198         boundary problems.  There is a word below the bottom of each\r
1199         stack, which ABORT clears before it starts interpreting. In\r
1200         addition to checking that both stacks have not overflowed, this\r
1201         routine checks those two words, to see if underflow has\r
1202         occurred.\r
1203 \r
1204 BUFFER  ( n --- buffer )\r
1205         Get a free buffer, assign it to block n, return buffer address.\r
1206         Will free a buffer by writing it, if necessary.  Does not\r
1207         actually read the block.  A bug in the fig LRU algorithm, which\r
1208         I have not fixed, gives the PREVious buffer if USE gets set to\r
1209         PREVious (the bug is that it happens).  This bug sometimes\r
1210         causes sector moves to become sector fills.\r
1211 \r
1212 BLOCK   ( n --- buffer )\r
1213         Get BUFFER containing block n, relative to OFFSET.  If block n\r
1214         is not in a buffer, bring it in.  Returns buffer address.\r
1215 \r
1216 (LINE)  ( line screen --- buffer C/L)\r
1217 XLINE   Bring in the sector containing the specified line of the\r
1218         specified screen.  Returns the buffer address and the width of\r
1219         the screen.  Screen number is relative to OFFSET.  The line\r
1220         number may be beyond screen 4, (LINE) will get the appropriate\r
1221         screen.\r
1222 \r
1223 .LINE   ( line screen --- )\r
1224 DOTLIN  Print the line of the screen as found by (LINE), suppress\r
1225         trailing BLANKS.\r
1226 \r
1227 SPACES  ( count --- )\r
1228         EMIT count spaces, for non-zero, non-negative counts.\r
1229 \r
1230 <#      ( --- )\r
1231 BEGHSH  Initialize HLD for converting a double integer.  Stores the PAD\r
1232         address in HLD.\r
1233 \r
1234 #>      ( d --- string length )\r
1235 ENDHSH  Terminate numeric conversion, drop the number being converted,\r
1236         leave the address of the conversion string and the length, ready\r
1237         for TYPE.\r
1238 \r
1239 SIGN    ( n d --- d )\r
1240         Put sign of n (as a flag) in front of the conversion string.\r
1241         Drop the sign flag.\r
1242 \r
1243 #       ( d --- d/base )\r
1244 HASH    Generate next most significant digit in the conversion BASE,\r
1245         putting the digit in front of the conversion string.\r
1246 \r
1247 #S      ( d --- dzero )\r
1248 HASHS   Convert d to a numeric string using # until the result is zero.\r
1249         Leave the double result on the stack for #> to drop.\r
1250 \r
1251 D.R     ( d width --- )\r
1252 DDOTR   Print d on the output device in the current conversion base,\r
1253         with sign, right aligned in a field at least width wide.\r
1254 \r
1255 D.      ( d --- )\r
1256 DDOT    Print d on the output device in the current conversion base,\r
1257         with sign, in free format with trailing space.\r
1258 \r
1259 .R      ( n width --- )\r
1260 DOTR    Print n on the output device in the current conversion base,\r
1261         with sign, right aligned in a field at least width wide.\r
1262 \r
1263 .       ( n --- )\r
1264 DOT     Print n on the output device in the current conversion base,\r
1265         with sign, in free format with trailing space.\r
1266 \r
1267 ?       ( adr --- )\r
1268 QDOT    Print signed word at adr, per DOT.\r
1269 \r
1270 MESSAGE ( n --- )\r
1271 MESS    If WARNING is 0, print "MESSAGE #n"; otherwise, print line n\r
1272         relative to screen 4, the line number may be negative.  Uses\r
1273         .LINE, but counter-adjusts to be relative to the real drive 0.\r
1274                 \r
1275                 In bif-c, add value of 2 for WARNING, for internal error message \r
1276                 strings.\r
1277 \r
1278 (ABORT) ( anything --- nothing )        ( anything *** nothing )\r
1279 IABORT  An indirection for ABORT, for ERROR, which may be modified\r
1280         carefully.\r
1281 \r
1282 ERROR   ( anything line --- IN BLK )    ( anything *** nothing )\r
1283         ( anything --- nothing )        ( anything *** nothing ) WARNING < 0\r
1284         Prints out the last symbol scanned and MESSAGE number line.  If\r
1285         WARNING is less than zero, ABORTs through (ABORT), otherwise,\r
1286         clears the parameter stack, pushes the INput cursor and\r
1287         interpretaion BLK, and QUITs.\r
1288 \r
1289 EDITOR  ( --- )                         in EDITOR               P\r
1290         Set the current interpretation vocabulary to EDITOR.\r
1291 \r
1292 QSYNC   ( --- )                         in EDITOR\r
1293         Synchronize the ECB cursor with R#.\r
1294 \r
1295 EBLK    ( --- vadr )                    in EDITOR\r
1296         USER variable containing the current editing block.\r
1297 \r
1298 CURSOR  ( --- adr )                     in EDITOR\r
1299         Calculates the address of the edit cursor, R#, within the\r
1300         current editing block, bringing that block in if necessary.\r
1301 \r
1302 QDUMP   ( adr --- )                     in EDITOR\r
1303         Dump the 256 bytes at adr to the screen memory, at the top half\r
1304         of the screen (bottom half of screen memory).\r
1305 \r
1306 QARROW  ( c --- c )\r
1307         ( c --- 0 )\r
1308         Adjust the cursor according to the key passed.  If the key is a\r
1309         cursor control key, return 0; otherwise, leave the key\r
1310         unchanged.  The regular back-arrow is used for cursor movement,\r
1311         so the shifted back-arrow is used for destructive backspace.\r
1312         Also, the up arrow is used for cursor movement, so caret is not\r
1313         available without escaping.  See QUICK.\r
1314 \r
1315 \r
1316 ****          Definitions/Routines in BIF6.A and BIF6B.A:\r
1317 \r
1318 \r
1319 (NUMBER)        ( d1 string --- d2 adr )\r
1320 INUMB   Convert the text at string into a number, accumulating the\r
1321         result into d1, leaving adr pointing to the first character not\r
1322         converted.  If DPL is non-negative at entry, accumulates the\r
1323         number of characters converted into DPL.\r
1324 \r
1325 NUMBER  ( ctstr --- d )\r
1326         Convert text at ctstr to a double integer, taking the 0 ERROR if\r
1327         the conversion is not valid.  If a decimal point is present,\r
1328         accumulate the count of digits to the decimal point's right into\r
1329         DPL (negative DPL at exit indicates single precision).  ctstr is\r
1330         a counted string -- the first byte at ctstr is the length of the\r
1331         string, but NUMBER ignores the count and expects a NUL\r
1332         terminator instead.\r
1333 \r
1334 WORDPAD ( --- vadr )\r
1335 WORDPD  The per-USER constant pointing to an intermediate\r
1336         buffer for text scanning.\r
1337 \r
1338 WORD    ( c --- )\r
1339         Scan a string terminated by the character c or ASCII NUL out of\r
1340         input; store symbol at WORDPAD with leading count byte and\r
1341         trailing ASCII NUL.  Leading c are passed over, per ENCLOSE.\r
1342         Scans from BLK, or from TIB if BLK is zero.  May overwrite the\r
1343         numeric conversion pad, if really long (length > 31) symbols are\r
1344         scanned.\r
1345 \r
1346 BS      ( --- c )\r
1347         The per-USER backspace constant.\r
1348 \r
1349 EXPECT  ( buffer n --- )\r
1350         Get up to n-1 characters from the keyboard, storing at buffer\r
1351         and echoing, with backspace editing, quitting when a CR is read.\r
1352         Terminate it with a NUL.\r
1353 \r
1354 QUERY   ( --- )\r
1355         EXPECT 128 (TWID) characters to TIB.\r
1356 \r
1357         ( --- )                                                 P\r
1358 NUBLK   End interpretation of a line or screen, and/or prepare for a new\r
1359         block.  Note that the name of this definition is an empty\r
1360         string, so it matches on the terminating NUL in the terminal or\r
1361         block buffer.\r
1362 \r
1363 FIND    ( namstr vocptr1 --- nfa vocptr2 )\r
1364         Search a vocabulary, and its parents, if necessary, for a\r
1365         definition called namstr.  namstr is a counted (leading count\r
1366         byte is ignored) string, vocptr1 is a pointer to a pointer to\r
1367         a vocabulary tree or subtree.  It will usually be the address of\r
1368         the per-USER variable ROOT or DROOT, but may be a pointer to a\r
1369         left or right link of an entry in the symbol tree.  nfa will be\r
1370         the name field address of the definition found, or a NULL.\r
1371         vocptr2 will be the pointer-pointer to the last vocabulary\r
1372         searched.  vocptr2 will be the last vocabulary searche.  See\r
1373         (FIND).\r
1374 \r
1375 -DFIND  ( --- nfa vocptr )      { -DFIND name } typical input\r
1376 DDFIND  Parse a word, then FIND, first in the definition vocabulary,\r
1377         then in the CONTEXT (interpretation) vocabulary, if necessary.\r
1378         Returns the address of the symbol table entry or a NULL, and the\r
1379         last vocabulary searched, per FIND.\r
1380 \r
1381 -IFIND  ( --- nfa vocptr )      { -DFIND name } typical input\r
1382 DIFIND  Same as -DFIND, except search the CONTEXT vocabulary first.\r
1383 \r
1384 NAME,   ( --- ctStrPtr length )\r
1385 NCOMMA  Store counted string at WORDPAD into dictionary, return HERE\r
1386         pointer and length of string.  Note that the count is not stored\r
1387         in the dictionary, but that the address returned will be the\r
1388         address to store the count at.  (The length of the names of\r
1389         definitions are stored after the actual names in the dictionary!)\r
1390                 \r
1391                 But in BIF-C, the lengths are stored with the strings, and the\r
1392                 address returned points to where the counted string was stored.\r
1393 \r
1394 FORE_MARK       ( --- )\r
1395 FOREMK  Set forward reference bit in LATEST definition, if FOREWARD is\r
1396         non-NULL.\r
1397 \r
1398 (INSTALL)       ( nfa vocptr --- )                              P\r
1399 PINSTA  Install the header at nfa into the specified vocabulary, hiding\r
1400         (SMUDGEing) any existing definitions of the same name in that\r
1401         vocabulary. In BIF-6809, vocptr was a pointer to the parameter \r
1402                 field of the vocabulary, and we follow that in BIF-C v. 0.\r
1403 \r
1404 0!      ( --- )\r
1405 INULL   Store 0 word at NULL pointer (address 0).\r
1406 \r
1407 ?0      ( --- )\r
1408 TNULL   Set warning to -1 and jmp to ERROR if the word at address 0\r
1409         (NULL pointer) is not 0.\r
1410 \r
1411 QUICK   ( n --- )                       in EDITOR\r
1412         Quick and dirty editor; edits sectors, not screens.  See above\r
1413         description.\r
1414 \r
1415 NODE.   ( nfa --- flag )\r
1416 NDOT    ID. with some formatting, extra information useful for\r
1417         debugging, and a keyboard pause/abort test.  Returns flag less\r
1418         than 0 if BREAK key was pressed.\r
1419 \r
1420 VISIT   ( defptr vocptr --- )\r
1421         Scan vocabulary at vocptr in ascending order, performing\r
1422         definition at defptr at every node.  defptr is an nfa, vocptr is\r
1423         the pfa of a vocabulary, per FIND and ROOT/DROOT.  The\r
1424         definition to be executed will have parameters of the same form\r
1425         as NDOT, doing something at a symbol tree node and leaving a\r
1426         termination flag.  VISIT checks for stack overflow and watches\r
1427         the termination flag between executions.  The VISITing\r
1428         definition may have other parameters, but if it changes the\r
1429         stack pointer from execution to execution VISIT will complain.\r
1430 \r
1431 VLIST   ( --- )\r
1432         Alphabetically list the definitions in the current vocabulary.\r
1433 \r
1434 \r
1435 ****          Definitions/Routines in BIF7.A and BIF7B.A:\r
1436 \r
1437 \r
1438 CREATE  ( --- )         { CREATE name } input\r
1439         Parse a name (length < 32 characters) and create a header,\r
1440         reporting first duplicate found in either the defining\r
1441         vocabulary or the context (interpreting) vocabulary.  (INSTALL)\r
1442         the header in the local vocabulary.\r
1443 \r
1444 CONSTANT        ( n --- )\r
1445 CONST   { value CONSTANT name } typical input\r
1446         CREATE a header, compile a call to XCON, compile the constant\r
1447         value.\r
1448 \r
1449 VARIABLE        ( init --- )\r
1450 VAR     { init VARIABLE name } typical input\r
1451         CREATE a header, compile a call to XVAR, compile the initial\r
1452         value init.\r
1453 \r
1454 USER    ( ub --- )\r
1455 USER    { uboffset USER name } typical input\r
1456         CREATE a header, compile a call to XUSER, compile the unsigned\r
1457         byte offset in the per-USER table.  The USER is entirely\r
1458         responsible for maintaining allocation!\r
1459 \r
1460 :       ( --- )                                                 P\r
1461 COLON   { : name sundry-activities ; } typical input\r
1462         If executing, record the data stack mark in CSP, CREATE a\r
1463         header, compile a call to XCOL, and set state to compile. (SCOMP\r
1464         is defined in this file.)  CONTEXT (interpretation) vocabulary\r
1465         is unchanged.\r
1466 \r
1467 ;       ( --- )                                                 P\r
1468 SEMI    { : name sundry-activities ; } typical input\r
1469         ERROR check data stack against mark in CSP, compile ;S, unSMUDGE\r
1470         LATEST definition, and set state to interpretation.\r
1471 \r
1472 ."      ( --- )                                                 P\r
1473 DOTQ    { ." something-to-be-printed " } typical input\r
1474         Use WORD to parse to trailing quote, if compiling, compile XDOTQ\r
1475         and string parsed, otherwise, TYPE string.\r
1476 \r
1477 [COMPILE]       ( --- )                                         P\r
1478 BCOMP   { [COMPILE] name } typical use\r
1479         -DFIND next WORD and COMPILE it, literally; used to compile\r
1480         immediate definitions.\r
1481 \r
1482 INTERPRET       ( --- )\r
1483 INTERP  Interpret or compile, according to STATE.  Searches words parsed\r
1484         in dictionary first, via -IFIND, then checks for valid NUMBER.\r
1485         Pushes or COMPILEs double literal if NUMBER leaves DPL\r
1486         non-negative.  ERROR checks the stack via ?STACK before\r
1487         returning to its caller.  Sensitive to COMPILE-ONLY bit in\r
1488         headers.\r
1489 \r
1490 QUIT    ( anything *** nothing )\r
1491         Clear return stack.  Then INTERPRET and, if not compiling,\r
1492         prompt with OK, in infinite loop.\r
1493 \r
1494 BIF     ( --- )                                                 P\r
1495         Makes BIF the current interpretation vocabulary.\r
1496 \r
1497 ASSEMBLER       ( --- )                                         P\r
1498 ASMBLR  Makes ASSEMBLER the current interpretation vocabulary.  Might\r
1499         ought not to be IMMEDIATE.\r
1500 \r
1501 DEFINITIONS     ( --- )\r
1502 DEFS    Makes the current interpretation vocabulary also the current\r
1503         defining vocabulary.\r
1504 \r
1505 ABORT   ( anything --- nothing )        ( anything *** nothing )\r
1506         Clear parameter stack, intialize the NULL vector, set STATE to\r
1507         interpret and BASE to DECIMAL, return to input from terminal,\r
1508         restore DRIVE OFFSET to 0, set interpret and define vocabularies\r
1509         to BIF, print out "6809 BIF Vx.x", and finally, QUIT.  Used to\r
1510         force the system to a known state and return control to the\r
1511         standard INTERPRETer.\r
1512 \r
1513 VOCABULARY      ( --- )         { VOCABULARY name } input\r
1514 VOCAB   Create a vocabulary entry with a NULL local pointer, linked by\r
1515         the parent pointer to the current defining vocabulary.  The\r
1516         vocabulary parameter passed to the various searching routines is\r
1517         usually a pointer to the parameter field of a vocabulary.  That\r
1518         way, the root is functionally identically to a left or right\r
1519         link in a node or leaf, particularly for insertion.\r
1520 \r
1521 (       ( --- )\r
1522 PAREN   Parse out a comment and toss it away.  This is probably not\r
1523         useful, but it leaves the first 32 characters in WORDPAD.\r
1524 \r
1525 DAD     ( nfa --- name linkadr flag )\r
1526         Search the parent vocabulary of the definition at nfa for nfa,\r
1527         returning the address of the first character of the definition's\r
1528         name, a pointer to the left or right link which links the\r
1529         definition in, and a flag indicating whether the definition is\r
1530         linked left or right.  ERROR if the definition can't be found.\r
1531         The return parameters are appropriate for REPEALing the\r
1532         definition.\r
1533 \r
1534 REPEAL  ( --- )\r
1535         Remove the CURRENT/LATEST definition from the dictionary, from\r
1536         the vocabulary in which it is defined.  Updates CURRENT, alsoe\r
1537         updates DROOT or ROOT and clears FOREWARD, if appropriate.  If\r
1538         the CURRENT definition is in a closed forward block, repeals the\r
1539         entire block, so that forward references aren't pointing to\r
1540         trash.\r
1541                 \r
1542                 Except that I never got that last part written and working. So \r
1543                 you have to do that by hand. It does clear FOREWARD if FOREWARD \r
1544                 is pointing to the REPEALed definition.\r
1545 \r
1546 FORGET  ( --- ) { FORGET name } input\r
1547         Parse out name of definition to FORGET to, -DFIND it, then\r
1548         REPEAL until it is removed from the dictionary.  Will not FORGET\r
1549         if definition is not found, if it is in a recursive block, or if\r
1550         it is below FENCE; the ERROR message will include the offending\r
1551         name.\r
1552                 \r
1553                 (Does it really?)\r
1554 \r
1555 \r
1556 ****                Definitions/Routines in BIFST.A\r
1557 \r
1558 \r
1559 COLD    COLD boot.  Initializes the system variables, prunes the\r
1560         dictionary of everything beyond the initial FENCE, then WARM\r
1561         boots.\r
1562 \r
1563 WARM    Resets stack areas and per-USER variables, clears the buffers,\r
1564         then yields control to BIF via ABORT.\r
1565 \r
1566 \r
1567 ****\r
1568 Definitions on the SCREENs disk follow.  The vocabulary names are\r
1569 abbreviated here under the definition names, A for ASSEMBLER, B for BIF,\r
1570 U for UTILITIES, ^a for ^asm-util.\r
1571 \r
1572 ****                            SCREEN 0\r
1573 Index to the screens disk.\r
1574 \r
1575 ****                            SCREEN 2\r
1576 Title page and copyright notice.\r
1577 \r
1578 ****                            SCREEN 3\r
1579 MON     ( --- )\r
1580 -       Call the debugging monitor: SWI followed by a jmp [,y++], so\r
1581         that BIF can be continued.\r
1582 \r
1583 After screen 2 creates MON, it updates FENCE to protect MON from WARM\r
1584 boots.  Will load in the active vocabulary.\r
1585 \r
1586 ****                         SCREENs 4 & 5\r
1587 Error and other Messages:\r
1588 0: number conversion/unknown definition, no message text.\r
1589 1: DATA STACK UNDERFLOW\r
1590 2: DICTIONARY FULL\r
1591 3: ADDRESS RESOLUTION ERROR for control structures\r
1592 4: HIDES DEFINITION IN some vocabulary\r
1593 5: NULL VECTOR WRITTEN\r
1594 6: DISC RANGE? disk sector number out of range\r
1595 7: DATA STACK OVERFLOW\r
1596 8: DISC ERROR! of some sort -- is your drive door closed?\r
1597 9: CAN'T EXECUTE A NULL!\r
1598 10: CONTROL STACK UNDERFLOW\r
1599 11: CONTROL STACK OVERFLOW\r
1600 12: ARRAY REFERENCE OUT OF BOUNDS\r
1601 13: ARRAY DIMENSION NOT VALID\r
1602 14: NO PROCEDURE TO ENTER\r
1603 15: ( was register error message for assembler )\r
1604 16:\r
1605 17: COMPILATION ONLY, USE IN DEFinition\r
1606 18: EXECUTION ONLY do not use while compiling\r
1607 19: CONDITIONALS NOT PAIRED where's your if/loop end statement?\r
1608 20: DEFINITION INCOMPLETE often same as 18, but hit ;\r
1609 21: IN PROTECTED DICTIONARY don't try to forget below FENCE.\r
1610 22: USE ONLY WHEN LOADING\r
1611 23: OFF CURRENT EDITING SCREEN an editor cursor problem\r
1612 24: DECLARE VOCABULARY\r
1613 25: DEFINITION NOT IN VOCABULARY\r
1614 26: IN FORWARD BLOCK\r
1615 27: ALLOCATION LIST CORRUPTED: LOST\r
1616 28: CAN'T REDEFINE nul!  You tried to CREATE something without a name.\r
1617 29: NOT FORWARD REFERENCE\r
1618 30: ( was message about IMMEDIATE )\r
1619 31:\r
1620 32:\r
1621 33: HAS INCORRECT ADDRESS MODE for 6809\r
1622 34: HAS INCORRECT INDEX MODE for 6809\r
1623 35: OPERAND NOT REGISTER in 6809\r
1624 36: HAS ILLEGAL IMMEDIATE for 6809\r
1625 37: PC OFFSET MUST BE ABSOLUTE pc-relative addressing error\r
1626 38: ACCUMULATOR OFFSET REQUIRED for indexing mode\r
1627 39: ILLEGAL MEMORY INDIRECTION for 6809\r
1628 40: ILLEGAL INDEX BASE for 6809\r
1629 41: ILLEGAL TARGET SPECIFIED for 6809 addressing mode or register\r
1630 42: CAN'T STACK ON SELF for push/pull, try other stack pointer\r
1631 43: DUPLICATE IN LIST of operands\r
1632 44: REGISTER NOT STACK trying to push on a non-stack register?\r
1633 45: EMPTY REGISTER LIST best supply some registers\r
1634 46: IMMEDIATE OPERAND REQUIRED for 6809\r
1635 47: REQUIRES CONDITION for control operator\r
1636 48:\r
1637 49: COMPILE-TIME STACK UNDERFLOW\r
1638 50: COMPILE-TIME STACK OVERFLOW\r
1639 \r
1640 ****                            SCREEN 6\r
1641 \r
1642 BYTE-DUMP       ( adr n --- )\r
1643 U       Dump n bytes to output device, right adjusted in 4 character\r
1644         columns.  Field width is not big enough if BASE is six or less.\r
1645 \r
1646 DUMP    ( adr n --- )\r
1647 B       Formatted dump to output device, with ASCII interpretation.\r
1648         Hard coded to 4 bytes per line.\r
1649 \r
1650 QLIST   ( n --- )\r
1651 B       QDUMP a block/sector and set the cursor to the middle of the\r
1652         screen so the dump remains visible.\r
1653 \r
1654 QINDEX  ( start end --- )\r
1655 B       QLIST block/sectors from number start to end, inclusive.\r
1656 \r
1657 L/SCR   ( --- n )\r
1658 U       Calculate the number of terminal lines per disc screen at\r
1659         run-time.  Sixteen, at present.\r
1660 \r
1661 ULIST   ( n --- flag )\r
1662 U       List screen n, with line numbers in the current base, leave\r
1663         BREAK key flag.  Uses C/L, to automatically adjust for screen\r
1664         width (if C/L is set), but you may not want to use this\r
1665         definition if you set C/L to something besides 32 or 64.\r
1666 \r
1667 ****                            SCREEN 7\r
1668 \r
1669 LIST    ( n --- )\r
1670 B       ULIST screen n, line numbers in decimal.\r
1671 \r
1672 INDEX   ( start end --- )\r
1673 B       Print comment lines (line 0, and line 1 if C/L < 41) of screens\r
1674         from start to end.\r
1675 \r
1676 TRIAD   ( n --- )\r
1677 B       List a printer page full of screens to the printer, formatted by\r
1678         C/L.  Line and screen number are in current base.  Lists the\r
1679         group containing screen n, will print 2 screens if C/L is 32,\r
1680         three if C/L is 64.  (Two may not fit well.)\r
1681 \r
1682 ****                            SCREEN 8\r
1683 \r
1684 HOME    ( --- )\r
1685 U       Put the cursor at the (CoCo 2) CRT screen HOME position.\r
1686 \r
1687 MID     ( --- )\r
1688 U       Put the cursor 8 lines down the (CoCo 2) CRT screen.\r
1689 \r
1690 CLS     ( --- )\r
1691 B       Clear the (CoCo 2) CRT screen.\r
1692 \r
1693 CAN-UP  ( adr -- adr )\r
1694 U       Clear the UPDATE bit (MSB) for the buffer whose block word is at\r
1695         adr.  The characters in the buffer should be stored at adr+2.\r
1696 \r
1697 W-BUF   ( adr --- adr )\r
1698 U       Write the characters at adr+2 to the sector specified at adr,\r
1699         clear the UPDATE flag.\r
1700 \r
1701 SAVE-BUF        ( adr --- adr )\r
1702 U       W-BUF, if UPDATEd.\r
1703 \r
1704 QSAVE   ( --- )\r
1705 B       Save the PREViously edited buffer, if it was UPDATEd.\r
1706 \r
1707 SAVE-BUFFERS    ( --- )\r
1708 B       Write all buffers flagged for UPDATE, clear UPDATE bits.\r
1709 \r
1710 QCAN    ( --- )\r
1711 B       Cancel UPDATE of PREViously edited buffer.\r
1712 \r
1713 ****                            SCREEN 9\r
1714 \r
1715 CANCEL-UPDATES  ( --- )\r
1716 B       Cancel UPDATEs of all buffers.\r
1717 \r
1718 RE-QUICK        ( --- )\r
1719 B       Re-edit PREVious buffer.\r
1720 \r
1721 .BUF    ( adr --- adr )\r
1722 U       Dump buffer characters at adr+2, showing the sector number\r
1723         indicated at adr.\r
1724 \r
1725 .BUFFERS        ( --- )\r
1726 B       Dump all buffers, with block number, per .BUF.\r
1727 \r
1728 .PREV   ( --- )\r
1729 B       Dump contents and block number of PREVious buffer, per .BUF.\r
1730 \r
1731 EDIT    ( n --- )\r
1732 B       QUICK edit block n, showing the block number.\r
1733 \r
1734 QPREV   ( --- )\r
1735 B       QUICK edit the PREVious block.\r
1736 \r
1737 ****                           SCREEN 10\r
1738 \r
1739 QOPY    ( src dest --- )\r
1740 B       Move content of block/sector src to block dest.  BUG: Doesn't\r
1741         copy if src is already in a buffer (problem with LRU).\r
1742 \r
1743 COPY    ( src dest --- )\r
1744 B       Copy SCREEN src to SCREEN dest.  Uses QOPY, so you should\r
1745         EMPTY-BUFFERS before using COPY.\r
1746 \r
1747 QBACK   ( start end --- )\r
1748 B       Copy blocks from start to end to the next higher disc, at the\r
1749         same sector offset.\r
1750 \r
1751 EEDIT   ( n --- )\r
1752 B       Erase and then EDIT block n.\r
1753 \r
1754 ****                           SCREEN 11\r
1755 \r
1756 RES-ERROR       ( --- )\r
1757 U       ERROR #3\r
1758 \r
1759 FORWARD ( --- )         { FORWARD name } input\r
1760 B       Compile a forward reference header: CREATE, set FOREWARD if not\r
1761         already set, compile jmp to RES-ERROR, unSMUDGE header.\r
1762 \r
1763 :RESOLVE        ( --- ) { :RESOLVE name } input                 P\r
1764 A       If the characteristic of name is a jmp to RES-ERROR, make it\r
1765         LATEST, re-SMUDGE it, change jmp address to HERE; if the header\r
1766         of name is the base of the forward block, clear FOREWARD.\r
1767         Forward blocks should end with the definition of the first\r
1768         forward reference in the block, to maintain the block's\r
1769         integrity.  (However, the FOREWARD USER variable can be modified\r
1770         by hand, if necessary.)\r
1771 \r
1772 :RES    ( --- )         { :RES name } input\r
1773 B       Do ASSEMBLER's resolve, then compile jmp <XCOL and switch state\r
1774         to compile.\r
1775 \r
1776 ;RES    ( --- )                                                 P\r
1777 B       ; but SMUDGE LATEST one more time.\r
1778 \r
1779 ****              SCREEN 11 does not continue LOADing!              ****\r
1780 \r
1781 ****                           SCREEN 12\r
1782 \r
1783 PL      ( --- )\r
1784 B       Print 80 ASCII characters starting with '!'.\r
1785 \r
1786 PT      ( --- )\r
1787 B       PL until any key is hit.\r
1788 \r
1789 PTEST   ( --- )\r
1790 B       PT, but send the output to the printer.\r
1791 \r
1792 ****                           SCREEN  13\r
1793 \r
1794 SLIST   ( start end --- )\r
1795 -       ULIST SCREENs to printer from start to end inclusive.\r
1796 \r
1797 ****                           SCREEN 14\r
1798 This contains some experimental stuff that I was using to test my a\r
1799 Sardis Technologies disk controller.\r
1800 \r
1801 ****                           SCREEN 15\r
1802 \r
1803 NAME    ( cfa --- )\r
1804 B       Convert the CFA on the stack to an nfa and ID. it.\r
1805 \r
1806 NAMES   ( adr n --- )\r
1807 B       NAME n icodes at adr.  Naively interprets anything as an icode.\r
1808 \r
1809 ****                           SCREEN 16\r
1810 ****                   The assembler starts here!                   ****\r
1811 \r
1812 ^asm-util       ( --- )\r
1813 A       Vocabulary for assembler support stuff.  (Note that the name is\r
1814         in lower case and looks funny when editing until the cursor\r
1815         moves over it.)\r
1816 \r
1817 DREG    ( n --- )       { n DREG name } input -> compile-time\r
1818 ^a      ( --- d ) -> run-time\r
1819         Define register double constants.  Most significant word is\r
1820         `RE', the index and operand encodings are masked into the least\r
1821         significant word.\r
1822 \r
1823 xx      ( --- d ) high word is HEX 5245\r
1824 A       The register double constants in hex:\r
1825         D  52458B00     A  52458608     B  52458509     PC 52458C05\r
1826         U  52454003     S  52456004     Y  52452002     X  52450001\r
1827         CC 5245EF0A     DP 5245EF0B\r
1828         Example: DP A EXG is exg dp,a\r
1829 \r
1830 #       ( --- n )\r
1831 A       Suffix constant for immediate values.  Becomes the high byte:\r
1832         4 # A LD is lda #4\r
1833 \r
1834 DPREG   ( --- adr )\r
1835 ^a      DP register emulator for the assembler.  A per-USER variable at\r
1836         offset HEX 42, initialized to whatever the load-time DP is.\r
1837 \r
1838 DPR     ( --- adr )\r
1839 A       Push the current DPREG value, as a constant.  To use as an\r
1840         absolute address, push a 0 or -1 after.\r
1841         Example: DPR 7 + 0 JMP is jmp <7\r
1842 \r
1843 SETDP   ( adr --- )\r
1844 A       Set the DPREG value, masks the low byte of adr out.\r
1845 \r
1846 ****                           SCREEN 17\r
1847 \r
1848 OFF,    (n b --- )\r
1849 ^a      Compile an index byte b with signed, constant, byte or word\r
1850         offset, n.  Sets bit 0 in the index byte if it compiles a word\r
1851         offset.\r
1852 \r
1853 OP,     ( u --- )\r
1854 ^a      Compile opcode u.  Compiles 16 bits if high byte of u is\r
1855         non-zero.\r
1856 \r
1857 ABS,    ( adr u1 u2 --- )\r
1858 ^a      Compile an absolute address mode (direct page or extended)\r
1859         op-code u1, oring u2 into u1 before compiling if the address is\r
1860         not in the direct page.\r
1861 \r
1862 PCOFF   ( adr n1 --- n2 flag )\r
1863 ^a      Generate a pc-relative offset n2 from adr, adjusted by n1 bytes\r
1864         of op-code/index.  Flags true if offset fit in a byte, false if\r
1865         it required 16 bits.\r
1866 \r
1867 ?ABS    ( d --- adr flag )\r
1868 ^a      Convert high word of d to flag showing true if high word was 0\r
1869         or -1, false otherwise.  A 0 or -1 high word indicates an\r
1870         absolute address as an operand.\r
1871         Example: HEX .FF20 B OR is orb $FF20\r
1872 \r
1873 PCR,    ( d b --- )\r
1874 ^a      ERROR if d is not absolute mode operand.  Calculate offset and\r
1875         compile index byte b and offset.\r
1876 \r
1877 ****                           SCREEN 18\r
1878 \r
1879 Auto-indexing address mode double constants, in ASSEMBLER vocabulary:\r
1880 -)      ( --- 4155.0082 )       ,-r\r
1881 )++     ( --- 4155.0081 )       ,r++\r
1882 )+      ( --- 4155.0080 )       ,r+\r
1883 --)     ( --- 4155.0083 )       ,--r\r
1884         Example: )++ X , D ST is std ,x++\r
1885 \r
1886 MASK,   ( b1 b2 --- )\r
1887 ^a      Compile the bit-or of the top two words's low bytes.\r
1888 \r
1889 REG,    ( u b --- )\r
1890 ^a      Convert a register offset specified by u to its extension byte\r
1891         representation, mask in the index register and indirection\r
1892         specifier b, and compile the resulting index byte.\r
1893 \r
1894 IXOFF,  ( n b --- )\r
1895 ^a      Generate the appropriate index extension byte for the constant\r
1896         offset n and indirection level specified, mask in the index\r
1897         register and indirection specifier b, and compile both the\r
1898         extension byte and the offset.  Handles zero and 5-bit offsets.\r
1899 \r
1900 EI,     ( d b --- )\r
1901 ^a      Compile a (completely specified) extended-indirect extension\r
1902         byte b and the absolute address d.\r
1903 \r
1904 ****                           SCREEN 19\r
1905 \r
1906 IX,     ( d n --- )\r
1907 ^a      Compile an index mode address operand.  n contains the index\r
1908         register and indirection level encoding, d contains the offset\r
1909         or auto-mode specification.  Zero offset must be explicit.  Does\r
1910         not block out unsupported [,r+] and [,-r] modes.\r
1911 \r
1912 ,       ( d1 --- d2 )\r
1913 A       Convert indexable register d1 to index mode specifier d2.\r
1914         Examples: 0. X , B OR is orb ,x\r
1915                   A X , JMP is jmp a,x\r
1916                   TABLE 0 PC , X LEA is leax table,pcr\r
1917 \r
1918 )       ( d1 --- d2 )\r
1919 A       Convert indexable register, absolute address, or index operand\r
1920         d1 to memory indirect operand.  Note that this will NOT\r
1921         interfere with comments.\r
1922         Examples: TABLE 6 + 0 PC ) JMP is jmp [6,pcr]\r
1923                   )++ S ) JSR is jsr ,s++\r
1924 \r
1925 ****                           SCREEN 20\r
1926 \r
1927 ACCM    ( n1 n2 n3 --- n4 )\r
1928 ^a      Convert op-code n1, register n2, and mask bits n3 to accumulator\r
1929         encoded op-code n4.  Used for encoding ACCM destination\r
1930         op-codes.\r
1931 \r
1932 UNARY   ( u --- )               >--> compile-time\r
1933 ^a      { u UNARY name } input  >-/\r
1934         ( do dx --- ) indexed modes >-\\r
1935         ( d --- ) non-indexed modes >--> run-time\r
1936         Unary op-code compiler -- compiles an assembler of unary\r
1937         op-codes with op-code (u) and name.  Run-time parameters: d is\r
1938         the destination register or address, dx is the index\r
1939         mode/register, do is the offset/auto mode.\r
1940         Examples: A NEG is nega\r
1941                   7. U , ROR is ror 7,u\r
1942 \r
1943 REG     ( d adr --- d u sz ) -- JSR\r
1944 ^a      ( d adr --- u sz )\r
1945         Encode binary destination register d into op-code from table at\r
1946         adr.  Table format is primary (byte), highest (byte), secondary\r
1947         (word) secondary (word) ....  Leave op-code u and size sz (-1 is\r
1948         word, 0 is byte) of register encoded.  Helps to reduce the\r
1949         complexity of the binary operators op-code map, see BINARY\r
1950         concerning constructing the tables.\r
1951 \r
1952 ****                           SCREEN 21\r
1953 \r
1954 #,      ( n u sz --- )\r
1955 ^a      Compile an immediate op-code u with immediate operand n of size\r
1956         byte, if sz == 0, or word, ERROR if op-code is ST or JSR.\r
1957 \r
1958 BINARY  ( ul b ub --- )                >--> compile-time\r
1959 ^a      { ul b ub BINARY name } input  >-/\r
1960         ( ds --- ) JSR                 >-\\r
1961         ( ds dd --- ) non-indexed mode >--> run-time\r
1962         ( do dx dd --- ) indexed mode  >-/\r
1963         Compile an assembler of binary operators, with primary op-code\r
1964         (accumulator form, any mode) ub, count of other codes (0, 1, or\r
1965         5) b, and optional list of other codes ul.  The list of other\r
1966         op-codes must be pushed on the stack in the order S, U, Y, X,\r
1967         and D (LD, ST, and CMP), or must be just the op-code for D (ADD\r
1968         and SUB).  Page escape codes must be included in the op-codes.\r
1969         Run-time operands: ds is the source, do is the source\r
1970         offset/auto mode, dx is the index mode/register, dd is the\r
1971         destination register. Example: 12 # D CMP is cmpd #12 -800. X )\r
1972         X LD is ldx [-800,x]\r
1973 \r
1974 REG-REG ( b --- )       { b REG-REG name } input -> compile-time\r
1975 ^a      ( d1 d2 --- ) -> run-time\r
1976         Compile an assembler of register d1 to register d2 moves.\r
1977         Examples: D Y EXG is exg d,y\r
1978                   A CC TFR is tfr a,c\r
1979 \r
1980 ****                           SCREEN 22\r
1981 \r
1982 REG-BITS        ( n --- vadr )\r
1983 ^a      1ARRAY of register bits for push/pull extension byte.  The\r
1984         Undefined slots set all bits to stabilize PACK.  Use the low\r
1985         word of a register specifier to index the array (see the DREG\r
1986         constants).\r
1987 \r
1988 PACK    ( n dl n --- n b )\r
1989 ^       Pack register list dl into result byte b.  Terminates when the\r
1990         n, which is not the high word of a register specifier, is DUPed\r
1991         and compared to HEX 5245; thus, any word or double which won't\r
1992         be interpreted as a register specifier (see DREG) will terminate\r
1993         the list, including the stack hole.  ERRORs on attempt to push a\r
1994         stack register on itself.  May underflow the parameter\r
1995         stack if the stack hole is corrupted with HEX 5245, of course,\r
1996         but will not attempt to draw more than 8 doubles from the stack\r
1997         unless REG-BITS is corrupted.\r
1998 \r
1999 MOVEM   ( b --- )       { b MOVEM name } input -> compile-time\r
2000 ^a      ( n dl d --- n ) -> run-time\r
2001         Compile a push or pull instruction assembler.  d is the stack\r
2002         register to push or pull.  See PACK.\r
2003         Example: D X Y U PSH is pshu d,x,y\r
2004         (But don't leave stray register specifiers on the stack!)\r
2005 \r
2006 ****                           SCREEN 23\r
2007 \r
2008 BR      ( d1 d2 --- )\r
2009 A       Assemble a branch on condition d2 to absolute address d1.\r
2010         Converts to PC relative, assembles a short branch if branch\r
2011         target is close enough.\r
2012         Example: LABEL 0 CCLR BR is bcc [LABEL]\r
2013 \r
2014 DCOND   ( n --- )       { n DCOND name } input  -> compile-time\r
2015 ^a      ( --- d )\r
2016         Compile a branch condition constant; high word is HEX 434F.\r
2017         Always (AL), never (NV), and subroutine (SR) are provided as\r
2018         DCONDs.\r
2019         Example: ' BMUL CFA 0 AL BR is bra BMUL\r
2020 \r
2021 CC-IMM  ( b --- )       { b CC-IMM name } -> compile-time\r
2022 ^a      ( d --- ) -> run-time\r
2023         Compile ORCC, ANDCC, EORCC, or CWAI assemblers.  The assemblers\r
2024         will ERROR if the operand is not immediate.\r
2025         Example: HEX EF # CWAI is cwai #$EF\r
2026 \r
2027 IMPLY   ( b --- )       { b IMPLY name } input >--> compile-time\r
2028 ^a      ( --- ) run-time\r
2029         Compile assemblers of implicit operand instructions.\r
2030         Example: NOP is nop\r
2031 \r
2032 ****        The next two SCREENs contain op-code assemblers.        ****\r
2033 See the compilers for run-time descriptions.  The odd organization keeps\r
2034 the trees balanced.  The assemblers, or, in other words, the mnemonics,\r
2035 are in the ASSEMBLER vocabulary.\r
2036 \r
2037 ****                           SCREEN 24\r
2038 \r
2039 BINARYs LD ST and CMP with their associated 16-bit register op-code\r
2040         lists.\r
2041 MOVEMs PUL PSH          UNARYs ROR ROL          IMPLYs RTS RTI\r
2042 BINARY SBC              DCOND SR (subroutine)   REG-REG TFR\r
2043 UNARY TST               BINARY SUB with D\r
2044 IMPLYs SWI2 SWI3 SWI SYNC                       BINARYs AND ADC\r
2045 UNARYs ASL ASR          BINARY ADD with D       IMPLY ABX\r
2046 DCOND CS                UNARYs COM CLR          DCOND AL (always)\r
2047 BINARY BIT              UNARY DEC               IMPLY DAA\r
2048 DCONDs HI MI EQ GE      REG-REG EXG             UNARY INC\r
2049 BINARY JSR              UNARY JMP               BINARY EOR\r
2050 DCONDs GT HS            IMPLY NOP               DCONDS LS PL\r
2051 \r
2052 ****                           SCREEN 25\r
2053 \r
2054 UNARYs LSR LSL          DCONDs LT NE            IMPLY MUL\r
2055 UNARY NEG               BINARY OR               CC-IMM ORCC\r
2056 DONCD NV (never)        IMPLY SEX (blush)       CC-IMMs ANDCC CWAI\r
2057 DCONDs VC VS CCLR (Carry CLeaR)\r
2058 \r
2059 EA-IX   ( n --- vadr )\r
2060 ^a      1ARRAY of translations from register (DREG) to LEA arguments.\r
2061 \r
2062 LEA     ( do dx dd --- )\r
2063 A       Assembler for LEA instructions.  do is the offset/auto mode, dx\r
2064         is the source index register, dr is the destination index\r
2065         register.\r
2066         Example: D Y , X LEA is leax d,y\r
2067 \r
2068 DCONDs LE LO\r
2069 \r
2070 ****                           SCREEN 26\r
2071 \r
2072 [CD]    ( --- dcfa )     { [CD] name } input                    P\r
2073 A       Produce the CFA of the following definition header, for use as a\r
2074         jump or indexing target.  If compiling, causes the code address\r
2075         to be compiled as a double literal; otherwise, pushes the cfa as\r
2076         a double, so the assemblers can use it for addressing.\r
2077 \r
2078 & ! ^   ( n1 n2 --- n3 )\r
2079 A       Aliases for AND OR and XOR for the assembler vocabulary.\r
2080 \r
2081 NEXT    ( --- )\r
2082 A       Assembler the NEXT instruction, jmp [,y++].\r
2083 \r
2084 ****    The assembler control constructs are patterned after FORTH\r
2085 control constructs, but test the Condition Code register.\r
2086 ****\r
2087 \r
2088 ****                           SCREEN 27\r
2089 \r
2090 INVERTCC        ( dcond --- ~dcond )\r
2091 ^a      Invert the assembler branch condition (double word) on top of\r
2092         stack.\r
2093 \r
2094 LIF     ( dcond --- daddr )\r
2095 A       Mark HERE as a double with the address in the low word and HEX\r
2096         4146 in the high word.  Assemble a long branch on the inverse of\r
2097         the condition given, and leave the mark.  Temporarily set the\r
2098         branch address to the RES-ERROR routine.\r
2099 \r
2100 IF      ( dcond --- daddr )\r
2101 A       Same as LIF, but assembles short branch with 0 offset.\r
2102 \r
2103 ****                           SCREEN 28\r
2104 \r
2105 FILL-IN ( dadr --- )\r
2106 ^a      Resolve offset of branch at mark to HERE, handle two, three, and\r
2107         four byte branches.\r
2108 \r
2109 ****                           SCREEN 29\r
2110 \r
2111 ELSE    ( daddr1 --- daddr2 )\r
2112 A       ERROR check the mark daddr1, mark HERE and assemble short branch\r
2113         always, via IF, and FILL-IN the previously marked IF or LIF.\r
2114 \r
2115 LELSE   ( daddr1 --- daddr2 )\r
2116 A       Same as ELSE except mark and assemble long branch always via\r
2117         LIF.\r
2118 \r
2119 ENDIF   ( daddr --- )\r
2120 A       ERROR check the mark, and resolve the IF or LIF.\r
2121 \r
2122 BEGIN   ( --- daddr )\r
2123 A       Mark indefinite loop beginning with HERE.  High word of mark is\r
2124         HEX 4142.\r
2125 \r
2126 UNTIL   ( daddr dcond --- )\r
2127 A       ERROR if daddr is not BEGIN mark; assemble branch on inverse of\r
2128         condition dcond to address marked in daddr.\r
2129 \r
2130 WHILE   ( daddr dcond --- adr daddr )\r
2131 A       ERROR if daddr is not BEGIN mark; assemble forward branch on\r
2132         inverse of condition dcond, leave BEGIN address on stack and\r
2133         extend mark with WHILE address and mark, HEX 4157.\r
2134 \r
2135 REPEAT  ( adr daddr --- )\r
2136 A       ERROR if not WHILE mark, assemble a branch to the BEGIN address\r
2137         and FILL-IN the WHILE address.\r
2138 \r
2139 LWHILE  ( daddr dcond --- adr daddr )\r
2140 A       Forced long branch version of WHILE.\r
2141 \r
2142 ****                           SCREEN 30\r
2143 \r
2144 :ASM    ( --- )\r
2145 A       CREATE a header and store the parameter stack pointer in CSP to\r
2146         mark the stack for assembler control construct and other errors.\r
2147 \r
2148 ;ASM    ( --- )\r
2149 A       ERROR check CSP and un-smudge the definion.  NEXT must be\r
2150         explicitly assembled.\r
2151 \r
2152 I-CODE  ( --- )\r
2153 A       Shift to high-level compiling.  (Assembles jmp <XCOL, changes\r
2154         state to compiling, changes interpretation vocabulary to\r
2155         definition vocabulary.)\r
2156 \r
2157 MACHINE ( --- )                                                 P\r
2158 A       Shift to assembly language.  (Compiles (MACHINE), changes state\r
2159         to interpretation, sets interpretation vocabulary to assembler.)\r
2160 \r
2161 ****                           SCREEN 32\r
2162                              Some Doubles\r
2163 \r
2164 D!      ( d adr --- )\r
2165 B       Store double d at adr.\r
2166 \r
2167 D@      ( adr --- d )\r
2168 B       Fetch double (two words) at adr.\r
2169 \r
2170 DOVER   ( d1 d2 --- d1 d2 d1 )\r
2171 B       Copy the second double (bytes 4-7) on the stack to the top.\r
2172 \r
2173 DSWAP   ( d1 d2 --- d2 d1 )\r
2174 B       Swap the top two doubles (bytes 0-3 with bytes 4-7).\r
2175 \r
2176 ****                           SCREEN 64\r
2177 \r
2178         This is an example showing use of the dictionary to associate\r
2179 pairs, from one of the textbooks I have.  I apologize to the source for\r
2180 not giving proper credit, but I can't find it.  It is included to show\r
2181 use of DOES> and to show how having the symbol table handy at run-time\r
2182 can be taken advantage of.  It builds pairs of objects linked to each\r
2183 other such that typing one in results in printing the other out.\r
2184 \r
2185 \r
2186 *******************************************************************************\r
2187                       Some Thoughts and Comments:\r
2188 \r
2189 \r
2190 Hey, it's not a professional package, so I can put this here if I want!\r
2191 \r
2192 One of the problems with BIF is the power of the 6809.  It is all too\r
2193 easy to use 6809 instructions instead of icodes.  This means that the\r
2194 6809 architecture gets woven into BIF, as mentioned at the end of the\r
2195 discussion on the virtual machine.\r
2196 \r
2197 BIF can probably be made to conform with one of the standards by moving\r
2198 the virtual machine routines to their associated definitions (XCOLON to\r
2199 COLON, XVAR to VARIABLE, etc.) and by making all code fields three-byte\r
2200 jumps (JSRs).  Direct threading will probably not be a problem, as long\r
2201 as code fields are uniform in size.\r
2202 \r
2203 The constant shifting between modes which I have done makes a built-in\r
2204 debugger more complex, as well.  One specific example is that using a\r
2205 macro instead of a jump to a NEXT inner interpreter makes debugging more\r
2206 complex.  If there is an inner interpreter, and if the low level\r
2207 routines are known to be error free, the debugger can simply be a jump\r
2208 inserted in the NEXT routine.  Use of a macro forces the debugger to be\r
2209 sensitive to the 6809 architecture, and requires either use of the SWI\r
2210 method (which can't be used in ROM), CPU emulation, or external\r
2211 breakpoint/single-step hardware.  The latter method is more complete,\r
2212 but inserting a debugging routine in the inner interpreter is often all\r
2213 that is necessary.\r
2214 \r
2215 A possible inner interpreter for a direct threaded FORTH (could be\r
2216 located in the direct page):\r
2217 \r
2218         NEXT    ldx ,y++                8~\r
2219                 jmp ,x                  3~      14~     (w/ jmp <NEXT)\r
2220 \r
2221 Or for indirect threading:\r
2222         NEXT    ldx ,y++                8~\r
2223                 jmp [,x]                6~      17~     (w/ jmp <NEXT)\r
2224 \r
2225 Compared to BIF:\r
2226                 jmp [,y++]              9~\r
2227 \r
2228 The apparent disadvantages of the above are at least partially offset by\r
2229 the fact that X will contain the CFA on entry to the characteristic\r
2230 routines.  In other words, X can substitute for W, and there is no need\r
2231 to store the CFA of the executing low level routine in an external\r
2232 register (on the stack, in the case of BIF).  Showing how this affects\r
2233 XCOL, for direct threading:\r
2234 \r
2235         someDEF jmp XCOL                4~\r
2236         . . .\r
2237         XCOL    pshs y                  7~\r
2238                 leay 3,x                5~\r
2239                 jmp <next               3~      19~, total 33~\r
2240 \r
2241 For indirect threading:\r
2242 \r
2243         someDEF fdb XCOL                0~\r
2244         . . .\r
2245         XCOL    pshs y                  7~\r
2246                 leay 2,x                5~\r
2247                 jmp <NEXT               3~      15~, total 32~\r
2248 \r
2249 Compared to BIF:\r
2250         someDEF jsr <XCOL               7~\r
2251         . . .\r
2252         XCOL    ldx ,s                  5~\r
2253                 sty ,s                  6~\r
2254                 tfr x,y (leay ,x)       6~ (4~)\r
2255                 jmp [,y++]              9~      33~, total 42~\r
2256 \r
2257 SURPRISED?  I was.  Of course, the characteristic routines must be a\r
2258 little careful to use or save X before they clobber it, but that isn't\r
2259 as difficult as it might seem.\r
2260 \r
2261 The direct page might still be used to locate the per-USER table, or\r
2262 might even contain it.  At first glance, it would appear too expensive\r
2263 to offset the DP register with a variable index.  But compare the\r
2264 following to the code in BIF:\r
2265 \r
2266         XUSER   tfr dp,a                6~\r
2267                 ldb [,s++]              10~     (stored as byte offset)\r
2268                 pshu d                  7~      (there's the address)\r
2269                 jmp [,y++]              9~      32~ compared to 34~\r
2270 \r
2271 If X is used for the temporary W register as in the indirect threaded\r
2272 inner interpreter example above, we can get the following, which speaks\r
2273 for itself:\r
2274 \r
2275         XUSER   tfr dp,a                6~\r
2276                 clrb                    2~      (showing word offset, )\r
2277                 addd 2,x                7~      (byte would be shorter)\r
2278                 pshu d                  7~\r
2279                 jmp <NEXT               3~      25~\r
2280 \r
2281 Ah, experience.  What we have to go through to get it!\r
2282 \r
2283 The key to FORTH and its dialects is found in ;CODE and DOES>.  By\r
2284 providing both characteristic behaviour and data allocation, FORTH words\r
2285 (symbols/definitions) are primitive objects.  A full object-oriented\r
2286 language could be generated with FORTH, but then you would probably have\r
2287 SMALLTALK!.  A standard compiling language keeps the symbol table, its\r
2288 data, and the code that accesses it entirely separate, and wastes a lot\r
2289 of code space doing so.  Professional FORTH systems can strip the symbol\r
2290 table out of compiled applications, if necessary, but the symbol table\r
2291 is available at run-time until the programmer is satisfied that his\r
2292 program is bug-free.  Moreover, the programmer has access to the same\r
2293 library used by the language, which is usually not the case with\r
2294 compiled languages, even with C.\r
2295 \r
2296 A careful examination of the overhead in FORTH shows that it is\r
2297 approximately the same as the overhead in a good C compiler.  While it\r
2298 would appear that constantly moving stuff on and off the stack would be\r
2299 a hindrance to progress, a second look reveals that the accumulator\r
2300 bottleneck requires this kind of movement.  I wish I had time and\r
2301 facilities to examine this specific question in relation to a large\r
2302 register set.\r
2303 \r
2304 I sometimes wonder if management paranoia (PROTECT OUR INTELLECTUAL\r
2305 PROPERTY!) is the primary reason FORTH, LISP, and SMALLTALK have not\r
2306 entirely supplanted the compiled languages.  If so, why is management\r
2307 willing to hide, protect, and hang on to code, but not willing to hang\r
2308 on to the engineers in whose brains the technology really resides?  Or\r
2309 in the converse, if management can see that it is sometimes necessary to\r
2310 let people go, why can't they see that there are some things that are\r
2311 not worth the cost of trying to protect their tools from?  And why can't\r
2312 they see that a intellectual property stolen by copying still requires a\r
2313 large investment in somebody's time to learn to use it?  Why doesn't\r
2314 public domain code get used?  Because it costs better than an order of\r
2315 magnitude more to learn how to use it than it does to get it.\r
2316 \r