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