6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Sep 28, 2024 1:05 pm

All times are UTC




Post new topic Reply to topic  [ 354 posts ]  Go to page Previous  1 ... 16, 17, 18, 19, 20, 21, 22 ... 24  Next
Author Message
PostPosted: Tue Mar 14, 2023 3:00 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 892

I mentioned another way to define THRU . Here are the block loading words in Fleet Forth.
These are in the kernel.
Code:
2VARIABLE HISTORY
: LINELOAD  ( LINE# BLK# -- )
   DUP 0=
   ABORT" CAN'T LOAD 0"
   RB DECIMAL
   BLK 2@ 2>R
   BLK !  C/L * >IN !
   INTERPRET  2R>
   BRANCH [ BLK.2! , ] -;
: LOAD  ( U -- )
   0 SWAP BRANCH
   [ ' LINELOAD >BODY , ] -;
: RAM  ( BLK#1 -- BLK#2 )
   RAM.OFFSET + ;
: FH  ( N1 -- N2 )
   BLK @ DUP UNDER+ ?EXIT
   SCR @ + ;
: DR+  ( BLK#1 #DR -- BLK#2 )
   7 AND  DR.OFS.PWR LSHIFT  + ;

HISTORY is set by WORD . HISTORY was originally added to Fleet Forth so WHERE could accurately display where an error originated.
LINELOAD takes a line number and a block number. It will load a screen starting at the specified line number.
LOAD loads the entire block. It branches to the beginning of LINELOAD .
Fleet Forth sets aside a range of block numbers for each disk as well as a range for the Ram Expansion Unit.
In the current version of Fleet Forth, RAM adds an offset of 16384 ($4000) to the number on the stack. Fleet Forth's BLOCK and BUFFER will access blocks higher than 16383 ($3FFF) from the Ram Expansion Unit
DR+ masks off the higher bits of a number and treats drive numbers 0 and 8 as the same device, 1 and 9 as the same device on up to treating 7 and 15 as the same device. DR+ adds the offset for the desired drive.
Code:
0 DR+   \
8 DR+   \ adds 0 to the number on the stack

1 DR+   \
9 DR+   \ adds 2048 to the number on the stack

2 DR+   \
10 DR+  \ adds 4096 to the number on the stack
...
7 DR+   \
15 DR+  \ adds 14336 to the number on the stack

RAM     \ adds 16384 to the number on the stack

Each drive, and the Ram Expansion Unit, sees its block range starting at 0.
Assume there is a disk with Forth blocks in drive 8 and drive 9 and both drives are open for block access.
Code:
1 LOAD \ loads block 1 from drive 8
1 8 DR+ LOAD \ also loads block 1 from drive 8
1 9 DR+ LOAD \ loads block 1 from drive 9
1 RAM LOAD \ loads block 1 from the Ram Expansion Unit

FH , from here, is a nice utility word from Leo Brodie's "Thinking Forth". When loading a screen, it adds the current block number to the number on the stack. This allows loading blocks (with LOAD or THRU ) relative from the currently loading block. When not loading a block, FH adds the current screen number to the number on the stack to assist editing.
THRU is defined in the system loader. This is its source in Fleet Forth.
Code:
: THRU  ( U1 U2 -- )
   >R
   BEGIN
      5 ?CR
      DUP U.  LOAD
      R@ HISTORY @ 1+ DUP>R U<
      DONE? OR
   ?LEAVE
      R>
   AGAIN -;

Yes, that is ?LEAVE used without a DO LOOP . Fleet Forth's ?LEAVE will, if the flag on the data stack is TRUE , drop two items from the return stack and pull a third item from the return stack and store it in IP .?LEAVE is used in Fleet Forth's definition of THRU to make it 2 bytes smaller than this:
Code:
: THRU  ( U1 U2 -- )
   >R
   BEGIN
      5 ?CR
      DUP U.  LOAD
      R@ HISTORY @ 1+ TUCK U<
      DONE? OR
   UNTIL
   R> 2DROP ;

Fleet Forth's source for THRU is not portable to other Forth systems with ?LEAVE in there and it doesn't matter. THRU is in the Controlled Reference Words of the Forth-83 Standard and it is in the ANSI Forth Standard. Any Forth system which uses blocks will likely have THRU .
I have not yet added --> except as a temporary definition. Should I choose to define it in the system, it will be defined in the system loader along with THRU .


Top
 Profile  
Reply with quote  
PostPosted: Sat Mar 18, 2023 12:45 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 892

Leo Brodie introduced the word \S in his book Thinking Forth. \S stops the rest of a screen from loading. Here is his source for \S
Code:
: \S   1024 >IN ! ;

In Fleet Forth it can be defined as this
Code:
: \S   B/BUF >IN ! ;

However, since the value of >IN is used in an unsigned comparison and WORD does not increment >IN beyond the size of the text stream, \S can be shortened further.
Code:
: \S   >IN OFF ;

This will also work with Fleet Forth.
Code:
: \S   2R> 2DROP ;

It can be made even smaller. I once mentioned that Fleet Forth's LEAVE is equivalent to using this phrase.
Code:
   2R> 2DROP EXIT

anywhere that phrase is used LEAVE can be used and vice versa.
For example
Code:
: TESTWORD
   10 0
   DO
      <DO SOME STUFF>
      <TEST> IF  LEAVE  THEN
   LOOP ;

can be rewritten as this
Code:
: TESTWORD
   10 0
   DO
      <DO SOME STUFF>
      <TEST> IF  2R> 2DROP EXIT  THEN
   LOOP ;

That phrase does the same thing as Fleet Forth's LEAVE , pull the top two loop parameters from the return stack and discard then exit to the address of the third parameter. The new TESTWORD is larger and slower, but it is functionally equivalent.

This
Code:
: \S   2R> 2DROP EXIT -;

compiles the same thing as this
Code:
: \S   2R> 2DROP ;

so Fleet Forth's source for \S can be changed to this
Code:
: \S   LEAVE -;



Top
 Profile  
Reply with quote  
PostPosted: Sat Mar 18, 2023 1:16 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8520
Location: Southern California
Quote:
Code:
IF  LEAVE  THEN

I use that enough that I've made it part of my kernel, as ?LEAVE.  It pays for itself in memory, and also runs a lot faster because the ?leave (the internal compiled by the immediate compile-only word ?LEAVE) is a primitive.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Sat Mar 18, 2023 1:29 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 892
GARTHWILSON wrote:
Quote:
Code:
IF  LEAVE  THEN

I use that enough that I've made it part of my kernel, as ?LEAVE.  It pays for itself in memory, and also runs a lot faster because the ?leave (the internal compiled by the immediate compile-only word ?LEAVE) is a primitive.

So have I. Since the redefinition of \S uses LEAVE , that is the one I used in the example.
Code:
?LEAVE
  2130          INX
  2131          INX
  2132   254 ,X LDA  W
  2134   255 ,X ORA  W 1+
  2136  2164    BNE ' (LOOP) >BODY 13 +
  2138  2174    BEQ NEXT
10

The first branch branches to the body of LEAVE , which LEAVE shares with (LOOP)
Code:
  2164          PLA       \ CFA OF LEAVE POINTS HERE
  2165          PLA
  2166          PLA
  2167          PLA
  2168          PLA       \ CFA OF EXIT POINTS HERE
  2169   251    STA IP
  2171          PLA
  2172   252    STA IP 1+

which falls into NEXT .
Fleet Forth's LEAVE and ?LEAVE are not compiled by secondaries.


Top
 Profile  
Reply with quote  
PostPosted: Tue Apr 11, 2023 2:30 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 892

Although it looks as though Fleet Forth's (LOOP) falls into NEXT , it really doesn't. The following is a disassembly of Fleet Forth's (LOOP) .
Code:
SEE (LOOP)
(LOOP)
  867         PLA
  868         TAY
  869         INY
  86A  8EB    BNE ' ?BRANCH >BODY 16 +
  86C         SEC
  86D         PLA
  86E    0  # ADC
  870  8EA    BVC ' ?BRANCH >BODY 15 +
  872  876    BVS
  874         PLA
  875         PLA
  876         PLA
  877         PLA
  878         PLA
  879   FB    STA IP
  87B         PLA
  87C   FC    STA IP 1+
  87E    1  # LDY
  880   FB )Y LDA IP
  882   FF    STA  W 1+
  884         DEY
  885   FB )Y LDA IP
  887   FE    STA  W
  889         CLC
  88A   FB    LDA IP
  88C    2  # ADC
  88E   FB    STA IP
  890  895    BCS
  892   FD    JMP  W 1-
  895   FC    INC IP 1+
  897   FD    JMP  W 1-
33
 OK

The two complementary branches, BVC and BVS, mark the end of (LOOP) . The string of PLA instructions which follow are the start of the code for LEAVE . It's header and code field are farther ahead and it's code field points to address $874.
Fleet Forth's kernel was rewritten to make this obvious and to give the new metacompiler one more test. The disassembly is as follows.
Code:
SEE LEAVE
LEAVE
  866         PLA
  867         PLA
  868         PLA
  869         PLA
  86A         PLA
  86B   FB    STA IP
  86D         PLA
  86E   FC    STA IP 1+
  870    1  # LDY
  872   FB )Y LDA IP
  874   FF    STA  W 1+
  876         DEY
  877   FB )Y LDA IP
  879   FE    STA  W
  87B         CLC
  87C   FB    LDA IP
  87E    2  # ADC
  880   FB    STA IP
  882  887    BCS
  884   FD    JMP  W 1-
  887   FC    INC IP 1+
  889   FD    JMP  W 1-
26
 OK
SEE (LOOP)
(LOOP)
  897         PLA
  898         TAY
  899         INY
  89A  900    BNE ' ?BRANCH >BODY 17 +
  89C         SEC
  89D         PLA
  89E    0  # ADC
  8A0  8FF    BVC ' ?BRANCH >BODY 16 +
  8A2  868 ^^ BVS ' LEAVE >BODY 2 +
D
 OK
SEE (+LOOP)
(+LOOP)
  8B0         INX
  8B1         INX
  8B2         CLC
  8B3         PLA
  8B4   FE ,X ADC  W
  8B6         TAY
  8B7         PLA
  8B8   FF ,X ADC  W 1+
  8BA  8FF    BVC ' ?BRANCH >BODY 16 +
  8BC  868 ^^ BVS ' LEAVE >BODY 2 +
E
 OK

It is now clear that (LOOP) branches into the body of ?BRANCH or into the body of LEAVE .

Another change to the kernel is having store, ! , fall into the body of 2DROP .
Code:
CODE !  ( N ADR -- )
   2 ,X LDA  0 X) STA  0 ,X INC
   0= IF  1 ,X INC  THEN
   3 ,X LDA  0 X) STA
   LABEL POPTWO ( N1 N2 -- )
   INX  INX
   LABEL POP
   INX  INX
   NEXT 0< NOT BRAN
   LABEL RUNG1
   // WILL BE PATCHED
   0 JSR           // >FORTH
   LABEL DO.?STACK
   0 ,             // ?STACK
   END-CODE

   ...

CODE 2DROP  ( N1 N2 -- )
   POPTWO  LATEST NAME> !
   END-CODE
CODE DROP  ( N1 -- )
   POP  LATEST NAME> !
   END-CODE

I've shown the disassembly for the loop words because the source can be difficult to follow for those not used to an assembler which uses RPN and the use of the auxiliary stack to temporarily store control flow data. The assembler and meta assembler both use the same size control flow data as Fleet Forth's high level control flow words.
Here is the source code for ?EXIT 0EXIT ?LEAVE LEAVE (LOOP) (+LOOP) ! and ?BRANCH .

Code:
CODE ?EXIT  ( F -- )
   INX  INX
   $FE ,X LDA  $FF ,X ORA
   0= IF CS>A               // EXIT
   0= NOT IF CS>A  END-CODE // NEXT
CODE 0EXIT  ( F -- )
   INX  INX
   $FE ,X LDA  $FF ,X ORA
   0= NOT IF CS>A           // EXIT
   0= IF CS>A  END-CODE     // NEXT
CODE ?LEAVE  ( F -- )
   INX  INX
   $FE ,X LDA  $FF ,X ORA
   0= IF CS>A               // LEAVE
   0= NOT IF CS>A  END-CODE // NEXT

CODE LEAVE
   A>CS A>CS THEN
   PLA  PLA
   PLA  PLA
   A>CS A>CS THEN
   A>CS A>CS THEN
   LABEL EXIT.BODY
   PLA  IP STA   PLA  IP 1+ STA
   THEN
   THEN
   THEN
   LABEL NEXT
   1 # LDY
   IP )Y LDA  W 1+ STA  DEY
   IP )Y LDA  W    STA  CLC
   IP LDA  2 # ADC  IP STA
   CS NOT IF
      W 1- JMP
   THEN
   IP 1+ INC
   W 1- JMP  END-CODE

CODE (LOOP)
   PLA  TAY  INY
   0= IF                 // TO ?BRANCH
   SEC  PLA  0 # ADC
   VS IF                 // TO ?BRANCH
   ' LEAVE @ 2+ VS BRAN
   CS-SWAP CS>A CS>A
   END-CODE
CODE (+LOOP)  ( N -- )
   INX  INX  CLC
   PLA  $FE ,X  ADC  TAY
   PLA  $FF ,X  ADC
   VS IF  CS>A           // TO ?BRANCH
   ' LEAVE @ 2+ VS BRAN
   END-CODE

CODE !  ( N ADR -- )
   2 ,X LDA  0 X) STA  0 ,X INC
   0= IF  1 ,X INC  THEN
   3 ,X LDA  0 X) STA
   LABEL POPTWO ( N1 N2 -- )
   INX  INX
   LABEL POP
   INX  INX
   NEXT 0< NOT BRAN
   LABEL RUNG1
   // WILL BE PATCHED
   0 JSR           // >FORTH
   LABEL DO.?STACK
   0 ,             // ?STACK
   END-CODE

CODE ?BRANCH  ( F -- )
   INX  INX
   $FE ,X LDA  $FF ,X ORA
   0= NOT IF
      LABEL 2.IP.+!
      CLC
      IP LDA  2 # ADC  IP STA
      CS IF  IP 1+ INC  THEN
      NEXT JMP
      A>CS THEN  A>CS THEN
      PHA
      A>CS THEN
      TYA  PHA  0 # LDY
   THEN
   LABEL BRANCH.BODY
   IP )Y LDA  PHA  INY
   IP )Y LDA  IP 1+ STA
   PLA  IP STA
   NEXT 2+ JMP  END-CODE



Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 15, 2023 2:20 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 892

I've mentioned Fleet Forth's WORD before. Reading through "standard" Forth and the following quotes from scotws motivated me to clarify something about Fleet Forth's WORD .
scotws wrote:
... but what this does is use PARSE-NAME (that's BL WORD COUNT in paleolithic Forths)...
scotws wrote:
... PARSE-NAME replaces WORD and just does ( "name" -- addr u ) while WORD ends up being BL WORD COUNT anyway...

Two of the drawbacks to WORD mentioned are the time used copying the parsed string to a transient area and the possibility of overwriting something beyond the transient area.
This is the source for Fleet Forth's WORD .
Code:
: WORD  ( C -- HERE )
   'STREAM
   BLK 2@ HISTORY 2!
   DUP >IN +!
   2PICK SKIP
   ROT 2PICK -ROT SCAN
   1- 0 MAX NEGATE >IN +!
   OVER - >HERE ;

The word >HERE just before the semicolon takes an address and count. It copies the string at that address to HERE as a counted string with a trailing blank. It will NOT copy more than 255 bytes! With the count byte and trailing blank, that is a maximum of 257 bytes at HERE which could get overwritten. Sure, the first 172 byes of PAD could possibly be overwritten. I wrote >HERE as a primitive so it would be fast.
I mentioned that >HERE takes an address and a count. If I wanted to support PARSE-NAME , I would have factored (WORD) out of WORD .
Code:
: (WORD)  ( C -- ADR CNT )
   'STREAM
   BLK 2@ HISTORY 2!
   DUP >IN +!
   2PICK SKIP
   ROT 2PICK -ROT SCAN
   1- 0 MAX NEGATE >IN +!
   OVER -
   ;
: WORD  ( C -- HERE )
   (WORD) >HERE ;
: PARSE-NAME  ( -- ADR CNT )
   BL (WORD) ;

Why haven't I done this? COUNT does not appear after WORD in any of the source files for Fleet Forth. The counted string from WORD is used as is. WORD is normally just used to parse names and numbers from the text stream.
I have another word to parse strings. It is used by the following words.
Code:
(
.(
"
."
ABORT"

I call this word CHAR ; however, the Ansi Forth standard has a word by that name which, along with [CHAR] , does what ASCII does in a Forth-83 system so I may rename Fleet Forth's CHAR . It works a lot like the Ansi Forth word PARSE in that it does not skip initial occurrences of the delimiter and it returns an address and count. It is different in that it will ABORT if the delimiter is not found.

WORD does not end up being BL WORD COUNT anyway. The two standards did things differently. It's not like PARSE-NAME just becomes PARSE-NAME >HERE anyway.


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 16, 2023 7:31 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 892
JimBoyd wrote:
I made a change to Fleet Forth's LINELOAD , which is used by LOAD . LINELOAD takes a line number and a screen number as parameters. It loads a given screen starting at the line specified.
I read somewhere (I don't remember where) a recommendation that LOAD should set BASE to decimal prior to loading a screen. I've given this some thought and can not really see a down side.

And now I have. I failed to consider the case where a screen might not contain source to compile but commands to run like a script. Just a reminder, a screen is a block which contains source to compile OR commands to execute. Consider a set of blocks which have screens of tests. Nothing gets compiled, the tests are run by loading the screen. Depending on the tests, it would be convenient to be able to set the BASE prior to loading.
Likewise, If the a screen changes BASE to something other than decimal, it will not be set to decimal for any screens chain loaded from that one with --> .
It is for these reasons that Fleet Forth's LOAD will no longer have a default base, nor will it restore BASE to whatever it was prior to loading. I believe this will result in more flexibility in how screens are used.

JimBoyd wrote:
As it is, I have been in the habit of specifying the number base at the start of a screen. With this modification, I will not have to specify the number base if I am using decimal for a particular screen.

This may not be necessary because Fleet Forth's NUMBER? accepts a leading conversion base specifier ($,# or %) in a numeric string.
The source for Fleet Forth's new LINELOAD and LOAD .
Code:
: LINELOAD  ( LINE# BLK# -- )
   DUP 0=
   ABORT" CAN'T LOAD 0"
   BLK 2@ 2>R
   BLK !  C/L * >IN !
   INTERPRET  2R>
   BRANCH [ BLK.2! , ] -;
: LOAD  ( U -- )
   0 SWAP BRANCH
   [ ' LINELOAD >BODY , ] -;



Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 17, 2023 1:05 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 252
JimBoyd wrote:
I failed to consider the case where a screen might not contain source to compile but commands to run like a script.
I use blocks like this all the time, and often have blocks that load other blocks with LOAD and THRU. I usually set the base, if it's important, right at the top and set it to decimal right at the end. I would like to make some words that save and restore the old base so that I can put it back the way it was, but it hasn't been a big enough issue to focus on and I just use the stack to hold the old base when I really need to do that.

You showed your co-routine method earlier in this thread and I was able to get your co-routine method to work in Tali (even though it's STC and your forth was ITC), so I will probably implement your RB (Restore Base) word that way when/if I get around to it.
JimBoyd wrote:
This may not be necessary because Fleet Forth's NUMBER? accepts a leading conversion base specifier ($,# or %) in a numeric string.
Tali2 supports this as well, and I've recently started to make use of it. It's actually a much better solution all around, in my opinion, because the person reading the code (which will probably be me at a later date) can easily tell $100 from #100 from %100 without having to figure out what the base is at that moment. It also allows for multiple bases to be used easily in the same screen, such as looping a decimal number of times while accessing a hex address with a binary mask.


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 22, 2023 4:28 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 892

I've added --> to Fleet Forth. I use it to link together all screens used by a given word. I do not use --> to link all screens in place of THRU . Since Fleet Forth's THRU is compatible with --> , I can use THRU to load a range of screens for some useful utilities while still chaining together the two screens spanned by a word such as (RR/W) .
Code:
SCR# 52
// (RR/W)
HEX
CODE (RR/W)  ( ADR BLK# R/WF CNT -- )
   DF09 STY  DF0A STY
   DF09 LDA  1F # CMP
   0= IF
      DF0A LDA  3F # CMP
      0= IF
         DF04 STY  4 ,X LDA
         .A ASL  5 ,X ROL
         .A ASL  5 ,X ROL
         DF05 STA
         5 ,X LDA  DF06 STA
         0 ,X LDA  DF07 STA
         1 ,X LDA  DF08 STA
         -->

SCR# 53
// (RR/W)
         6 ,X LDA  DF02 STA
         7 ,X LDA  DF03 STA
         2 ,X LDA  90 # ORA  DF01 STA
         BEGIN
            DF00 BIT
         VS UNTIL
         INX  INX  INX  INX
         POPTWO JMP
      THEN
   THEN
   >FORTH
   TRUE ABORT" NO REU" -;
' (RR/W) IS RR/W

(RR/W) spans the screens 52 and 53 so they are linked together with --> at the bottom of screen 52; however, they can still be loaded with the screens in the range 46 - 78. If I have an idea to improve (RR/W) , I can load all of it just by loading screen 52. This loads (RR/W) , and only (RR/W) , for testing. This use of --> to chain together all the screens spanned by a word, and using it with a compatible version of THRU , rather than using --> to replace the function of THRU , negates one of the arguments against --> ; specifically, the argument that the use of --> precludes the ability to load individual screens. The way I use --> , the only screens which can not be loaded individually are the ones which should not be loaded individually.


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 24, 2023 6:50 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 252
JimBoyd wrote:

This use of --> to chain together all the screens spanned by a word, and using it with a compatible version of THRU , rather than using --> to replace the function of THRU , negates one of the arguments against --> ; specifically, the argument that the use of --> precludes the ability to load individual screens. The way I use --> , the only screens which can not be loaded individually are the ones which should not be loaded individually.
That is very good work. The Forth-83 standard lists both --> and THRU as "controlled reference words" (eg. you don't have to provide them to meet the standard, but if you do provide them they should have defined behavior) and I always thought they were two different ways to solve the same issue (code that spans multiple screens). It looks like --> was dropped in the 94 standard and THRU was officially adopted into the "Block Extension" word set. The advantage of your forth having both words is that you are able to load older FIG Forth code as well as newer code.

I can see the advantage to having --> around (when it's like your version that is compatible with THRU) to ensure that a multiscreen definition of a single word always has the full definition loaded.


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 30, 2023 7:56 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 892

--> is a very simple word.
Code:
: -->  ( -- )
   1 BLK +!  >IN OFF ; IMMEDIATE

Here are generic versions of LOAD and THRU which are compatible with --> .


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 30, 2023 9:03 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 892

I've made some changes to Fleet Forth's multitasker.
UNLINK-TASK has been removed in an effort to keep the multitasker small.
UNLINK-ALL has been replaced with UNLINK .UNLINK is integrated into the kernel. The source for UNLINK-ALL
Code:
: UNLINK-ALL  ( -- )
   [ ASSEMBLER UP @ ] LITERAL
   DUP UP !  ENTRY ! ;   FORTH

and the source for a subroutine used by the WARM and COLD start routines.
Code:
HSUBR (WARM)
   SEI
   $2F # LDA  0 STA
   $36 # LDA  1 STA
   USER.DATA    LDA  UP    STA
   USER.DATA 1+ LDA  UP 1+ STA
   $6C # LDA  W 1- STA
   'THERE USER.DATA - 1- # LDY
   BEGIN
      USER.DATA ,Y LDA  UP )Y STA
      DEY
   0< UNTIL
   CLI
   >FORTH
      SP! AP! [COMPILE] [
      IORESET SINGLE DECIMAL
      PAGE BOOTCOLORS
   >ASSEM
      RTS
   END-CODE

Some of the functionality of (WARM) has been factored out into the new code word UNLINK .
Code:
CODE UNLINK  ( -- )
   USER.DATA    LDA  UP    STA
   USER.DATA 1+ LDA  UP 1+ STA
   'THERE USER.DATA - 1- # LDY
   BEGIN
      USER.DATA ,Y LDA  UP )Y STA
      DEY
   0< UNTIL
   NEXT JMP  END-CODE

Here is the new subroutine (WARM) .
Code:
HSUBR (WARM)
   SEI
   $2F # LDA  0 STA
   $36 # LDA  1 STA
   $6C # LDA  W 1- STA
   CLI
   >FORTH
      UNLINK
      SP! AP! [COMPILE] [
      IORESET SINGLE DECIMAL
      PAGE BOOTCOLORS
   >ASSEM
      RTS
   END-CODE

TASK and ACTIVATE have also been modified. They now support partitioning the auxiliary stack.
Code:
: ACTIVATE  ( TCF-ADR TASK-ADR -- )
   DUP WAKE
   TUCK  RP0 LOCAL @ 1- DUP>R !
   DUP SP0 LOCAL @ R@ 1- C!
   DUP TOS LOCAL R> 2- SWAP!
       AP0 LOCAL  @ DUP ! ;

: TASK  ( U AP0 SP0 RP0 -- )
   CREATE
        ( -- TADR )
      HERE RP0 LOCAL !
      HERE SP0 LOCAL !
      HERE AP0 LOCAL !
      // OPTIONAL
      #10 HERE BASE LOCAL !
      HERE #USER + HERE DP LOCAL !
      #12 UMAX ALLOT ;

The way ACTIVATE works is different. It now takes the address of a thread of high level Forth, such as the PFA , and the address of a task.
Here is the creation of a sample task:
Note: since this is on a Commodore 64, just think of each // as \.
Code:
DECIMAL
#USER 80 +  // 80 BYTES FOR 'HERE'
AP0 @ 42 -  // HALF OF AUX STACK
SP0 @ 62 -  // HALF OF DATA STACK
RP0 @ 128 - // HALF OF RETURN STACK
TASK BGTASK

Here is linking and activating.
Code:
: FLASH  ( -- )
   BEGIN
      $D020 C@ 1+ BORDER  // INCREMENT THE BORDER COLOR
      60 JIFFIES          // WAIT 1 SECOND
   AGAIN -;

BGTASK LINK-TASK
' FLASH >BODY BGTASK ACTIVATE
MULTI  // ENABLE MULTITASKING

PAUSE is not in the source for FLASH because JIFFIES calls DJIFFIES which has PAUSE .
A word of caution! FORGET switches off multitasking but does not unlink the tasks. After the use of FORGET it is the programmers responsibility to be certain none of the linked tasks or the words they run have been forgotten.
I could update FORGET to call UNLINK . It would be the programmers responsibility to relink and wake the tasks after the use of FORGET .


Top
 Profile  
Reply with quote  
PostPosted: Fri May 05, 2023 7:05 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 892
SamCoVT wrote:
I can see the advantage to having --> around (when it's like your version that is compatible with THRU) to ensure that a multiscreen definition of a single word always has the full definition loaded.


Yes, having all of a multi screen definition loaded when the first screen of said definition is loaded is nice. Fleet Forth has the word FH from Leo Brodie's Thinking Forth. After editing a screen, I can load it with the phrase 0 FH . It would be convenient after editing a word spanning multiple screens to be able to type 0 FH and load the new word regardless of which screen of a multi screen definition I was just editing. I would have liked to have such a feature back when I replaced PUSH and PUT with AYPUSH and AYPUT in Fleet Forth.
I've found a way to do just that. --> is redefined so it skips loading the comment line of the next block.
Code:
: -->  ( -- )
   1 BLK +!  C/L >IN ! ; IMMEDIATE

And a new word is added.
Code:
: <--  ( -- )
   TRUE BLK +!  >IN OFF ; IMMEDIATE

Here is Fleet Forth's BLOCK
Code:
SCR# 112
0: // BLOCK
1: CODE BLOCK  ( BLK -- ADR )
2:    DEY
3:    BLK/BUF STY
4:    ' MRU >BODY    LDA  W    STA
5:    ' MRU >BODY 1+ LDA  W 1+ STA
6:    6 # LDY
7:    W )Y LDA  0 ,X CMP
8:    0= IF
9:       INY  W )Y LDA  1 ,X CMP
A:       0= IF
B:          INY  (W)PUT JMP
C:       THEN
D:    THEN
E:    -->
F:

SCR# 113
0: // BLOCK
1:    >FORTH
2:    #BUF 1+ 2
3:    ?DO
4:       DUP I >BT @ =
5:       IF
6:          DROP I UNLOOP
7:          AHEAD CS>A
8:       THEN
9:    LOOP
A:       LRU 2+ 2+ @
B:       IF
C:          LRU 2@ 0 B/BUF R/W
D:          LRU 2+ 2+ OFF
E:       THEN
F:       -->

SCR# 114
0: // BLOCK BUFFER
1:       BLK/BUF C@
2:       IF
3:          LRU ON
4:          LRU 2+ @ DUP B/BUF TRUE FILL
5:          OVER 1 B/BUF R/W
6:       THEN
7:       LRU ! #BUF
8:    A>CS THEN
9:    DUP >BT MRU 6 CMOVE
A:    MRU 1 >BT ROT 6 * CMOVE>
B:    MRU 2+ @ ;
C:
D: CODE BUFFER  ( BLK# -- ADR )
E:    ' BLOCK @ 1+  LATEST NAME> !
F:    END-CODE

Here is the modified source.
Code:
SCR# 112
0: // BLOCK
1: CODE BLOCK  ( BLK -- ADR )
2:    DEY
3:    BLK/BUF STY
4:    ' MRU >BODY    LDA  W    STA
5:    ' MRU >BODY 1+ LDA  W 1+ STA
6:    6 # LDY
7:    W )Y LDA  0 ,X CMP
8:    0= IF
9:       INY  W )Y LDA  1 ,X CMP
A:       0= IF
B:          INY  (W)PUT JMP
C:       THEN
D:    THEN
E:    -->
F:

SCR# 113
0: <-- BLOCK
1:    >FORTH
2:    #BUF 1+ 2
3:    ?DO
4:       DUP I >BT @ =
5:       IF
6:          DROP I UNLOOP
7:          AHEAD CS>A
8:       THEN
9:    LOOP
A:       LRU 2+ 2+ @
B:       IF
C:          LRU 2@ 0 B/BUF R/W
D:          LRU 2+ 2+ OFF
E:       THEN
F:       -->

SCR# 114
0: <-- BLOCK BUFFER
1:       BLK/BUF C@
2:       IF
3:          LRU ON
4:          LRU 2+ @ DUP B/BUF TRUE FILL
5:          OVER 1 B/BUF R/W
6:       THEN
7:       LRU ! #BUF
8:    A>CS THEN
9:    DUP >BT MRU 6 CMOVE
A:    MRU 1 >BT ROT 6 * CMOVE>
B:    MRU 2+ @ ;
C:
D: CODE BUFFER  ( BLK# -- ADR )
E:    ' BLOCK @ 1+  LATEST NAME> !
F:    END-CODE

Here are the same three screens with most of the lines removed.
Code:
SCR# 112
0: // BLOCK
1: CODE BLOCK  ( BLK -- ADR )
E:    -->

SCR# 113
0: <-- BLOCK
F:       -->

SCR# 114
0: <-- BLOCK BUFFER
D: CODE BUFFER  ( BLK# -- ADR )
E:    ' BLOCK @ 1+  LATEST NAME> !
F:    END-CODE

By replacing the end of line comment word with <-- in the second and third screens used for BLOCK , I can load any one of the screens for BLOCK and all three will be loaded in the correct order.
When a screen starting with <-- is loaded by LOAD or THRU , the screen does not finish loading. loading resumes with the previous screen. This continues until loading resumes with a screen not having <-- . That screen loads normally. Assuming that screen has --> , loading resumes with the next screen but the comment line is skipped.


Top
 Profile  
Reply with quote  
PostPosted: Sun May 07, 2023 11:49 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 892
There are more changes for Fleet Forth's multitasker.
The data used to initialize the first six user variables has been changed so the main task is always awake by default.
The old system user area boot up values.
Code:
// SYSTEM USER AREA BOOT UP VALUES
USER.AREA ,    // ENTRY
   0 ,         // READY
   0 ,         // TOS
'RP0 ,         // RP0
'SP0 ,         // SP0
'AP0 ,         // AP0

The new values.
Code:
// SYSTEM USER AREA BOOT UP VALUES
USER.AREA ,    // ENTRY
TRUE ,         // READY
   0 ,         // TOS
'RP0 ,         // RP0
'SP0 ,         // SP0
'AP0 ,         // AP0

UNLINK has been added to FORGET just before SINGLE so FORGET and EMPTY will unlink all tasks.
TASK gives the created task the default of running the loop in STOP .
Code:
: STOP  ( -- )
   BEGIN
      READY OFF  PAUSE
   AGAIN -;

With these changes it is no longer necessary for LINK-TASK to put a task to sleep before linking it.

The multitasker has been moved from the utilities disk to the system loader disk. It is now loaded whenever the system is added to a new Fleet Forth kernel.


Top
 Profile  
Reply with quote  
PostPosted: Mon May 08, 2023 12:37 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 892
I once mentioned that my Forth would not have a permanent stack display and it will not; however, there is a way to add a stack display to the top of the screen on an as needed temporary basis. This could be handy when hand tracing yet to be compiled (as in, not finished) forth words.
I was trying to think of a simple background task to demonstrate the multitasker when I thought of this.
Fleet Forth's interpret has the word PAUSE as the first word in the interpreter loop.
Code:
: INTERPRET
   BEGIN
      PAUSE NAME C@ 0EXIT
      HERE I/C
   AGAIN -;

Fleet Forth's IS only works with DEFERred words and its TO only works with VALUEs. When compiling, they both compile (IS) . (IS) will alter the first cell of the parameter field of any word.
It is used to define words to 'patch' the interpreter.
Code:
: TOP.S
   $400 #160 BLANK
   XY 2>R  CHARS @ >R
   0 1 AT-XY CHARS OFF .S
   R> CHARS !  2R> AT-XY ;
: TOP.S.ON  ( -- )
   ['] TOP.S (IS) INTERPRET ;
: TOP.S.OFF  ( -- )
   ['] PAUSE (IS) INTERPRET ;
: PAGE
    PAGE  CR CR CR CR ;

TOP.S saves the current screen coordinates as well as the number of characters emitted since the last page or carriage return. It sets the screen coordinates to the beginning of the second line and displays the stack contents before restoring the screen coordinates and the number of characters emitted.
TOP.S.ON and TOP.S.OFF switch on and off this capability.
The new PAGE is to leave room for the stack display.
Because task switching can occur in .S , multitasking still works while interpreting/compiling.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 354 posts ]  Go to page Previous  1 ... 16, 17, 18, 19, 20, 21, 22 ... 24  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron