6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Nov 21, 2024 6:31 pm

All times are UTC




Post new topic Reply to topic  [ 354 posts ]  Go to page Previous  1 ... 13, 14, 15, 16, 17, 18, 19 ... 24  Next
Author Message
PostPosted: Tue May 10, 2022 3:43 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
I can't think of any situation where STATE would be something other than 0 or FFFF. I would think that if it were, it'd be because something corrupted it, meaning it would be invalid anyway. If that happened, you'd probably have additional problems to worry about.

_________________
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: Tue May 10, 2022 5:19 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
I'm pretty sure that I read of an example somewhere a few years back where an advanced user would decrement or increment STATE with [ and ] to allow some form of nested compilation, but I can't remember any other details.

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
PostPosted: Tue May 10, 2022 5:26 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
barrym95838 wrote:
I'm pretty sure that I read of an example somewhere a few years back where an advanced user would decrement or increment STATE with [ and ] to allow some form of nested compilation, but I can't remember any other details.

Might it have been for conditional compilation?

_________________
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: Tue May 10, 2022 5:35 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
GARTHWILSON wrote:
Might it have been for conditional compilation?

Maybe. The concept flew over my head at the time, but I took a swipe at it and stuffed it into a dusty corner of my brain, hoping to return later and analyze it better. Later is still waiting, and that dusty corner is now covered by a pile of laundry ...

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
PostPosted: Sat May 14, 2022 12:16 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895
GARTHWILSON wrote:
I can't think of any situation where STATE would be something other than 0 or FFFF. I would think that if it were, it'd be because something corrupted it, meaning it would be invalid anyway. If that happened, you'd probably have additional problems to worry about.


I was being excessively cautious, but I was thinking of something along the lines of building an execution table by doing this
Code:
CREATE TABLE1
   ] ROT -ROT SWAP [

instead of this
Code:
CREATE TABLE1
   ' ROT ,  ' -ROT ,  ' SWAP ,

This could also work.
Code:
CREATE TABLE1
   STATE ON ROT -ROT SWAP [

In Fleet Forth, the following would not work.
Code:
CREATE TABLE1
   1 STATE ! ROT -ROT SWAP [

Since STATE is only supposed to be manipulated by [ and ] , manipulating STATE directly, as in the last two examples, should be avoided.
That being the case, I will leave (I/C) , the heart of Fleet Forth's interpreter, as is.


Top
 Profile  
Reply with quote  
PostPosted: Sat May 14, 2022 12:29 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895
barrym95838 wrote:
GARTHWILSON wrote:
Might it have been for conditional compilation?

Maybe. The concept flew over my head at the time, but I took a swipe at it and stuffed it into a dusty corner of my brain, hoping to return later and analyze it better. Later is still waiting, and that dusty corner is now covered by a pile of laundry ...


I would think that in addition to conditional compiling, one would want conditional interpretation included since code words are assembled while interpreting.
Here is Fleet Forth's source for conditional compiling.
Code:
:NONAME  ( NL1 ADR -- NL2 )
         ( NL1 ADR -- )
   DUP  5 " [IF]"   TEXT= ABS UNDER+
   DUP  7 " [THEN]" TEXT= UNDER+
        7 " [ELSE]" TEXT= OVER 1 =
   AND +  ?DUP ?EXIT
   ['] (I/C) IS I/C ;
: [THEN] ; IMMEDIATE
: [ELSE]  ( -- )
   1  [ ROT ] LITERAL IS I/C ;
   IMMEDIATE
: [IF]  ( FLAG -- )
   ?EXIT
   [COMPILE] [ELSE] ; IMMEDIATE

A system which increments and decrements STATE could do so for some other purpose, but I can't imagine what.


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 12, 2022 10:01 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895
GARTHWILSON wrote:
(Whether rounded or truncated, the result is usually inexact anyway.)


The accuracy for small numbers can be improved. The word DSQRT takes a 64 bit number (a quadruple number or two doubles in Fleet Forth) and returns a double. The input could also be considered a mixed fraction consisting of two unsigned doubles where the top double is the integer part and the lower double is the fraction part. In this case the double number result from DSQRT would be a mixed fraction with the top cell the integer part and the lower cell the fraction part.
Here is a word to take a possible improper mixed fraction (the numerator might be larger than the denominator) and fix it.
Code:
: MFIX  ( UD1 U1 U2 -- UD2 U3 U2 )
   >R  0 R@  UM/MOD 2SWAP 0 -ROT D+
   ROT R> ;

And a word to convert that to a fixed point number consisting of a double fraction and a double integer.
Code:
: FIXED  ( UD1 U1 U2 -- UD2 UD3 )
   DUP>R 0 -ROT UM/MOD SWAP
   0 SWAP R> UM/MOD NIP
   SWAP 2SWAP ;

When the parameter for DSQRT is a fixed point number (a mixed fraction with 32 bits for each part as I've described) , the result can be displayed with this word.
Code:
: .RESULT  ( UD -- )
   1 U.R ." ."
   3 0
   DO
      1000 UM*  0 <# # # # #> TYPE
   LOOP
   DROP ;

The high cell is displayed as is since it is the integer portion. The DO LOOP extracts and displays the fractional portion three decimal places at a time.
For this mixed fraction: 2. 0 1 (which can also be entered as 0. 2.), the following:
Code:
2. 0 1 FIXED DSQRT .RESULT

Code:
0. 2. DSQRT .RESULT

returns this result:
1.414199829
which should be within 0.001 percent of the correct answer.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 16, 2022 2:31 am 
Offline

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

For greater precision when the integer portion of the parameter for DSQRT is no bigger than an unsigned single (0-65535), the following word can be used to take an integer with a fraction and convert it to a 64 bit fixed point number, consisting of two Forth double numbers, where the integer portion is only 16 bits.
Code:
: FIXED  ( U NUM DEN -- UT U )
   DUP>R 0 -ROT UM/MOD SWAP
   0 SWAP R@ UM/MOD SWAP
   0 SWAP R> UM/MOD NIP
   SWAP 2SWAP SWAP ;

In the stack comments, UT means unsigned triple.
Here is a word to 'clean up' sloppy fractions.
Code:
: MFIX  ( U U2 U3 -- U4 U5 U3 )
   >R  0 R@  UM/MOD  UNDER+  R> ;

And an appropriate version of .RESULT
Code:
: .RESULT  ( UD -- )
   256. UMD*  1 D.R ." ."
   3 0
   DO
      1000. UMD*  <# # # # #> TYPE
   LOOP
   2DROP ;

UMD* multiplies two double numbers and produces a quadruple number.
.RESULT first multiplies the double number result by the double number 256. to produce a quadruple number result. The top double number is the integer portion of the result.
As with the other version of .RESULT , the DO LOOP extracts and displays the fractional portion three decimal places at a time.
Here is the source for UMD* used in this version of .RESULT
Code:
: UMD*  ( UD1 UD2 -- UQ )
  // UD1 - B A  UD2 - D C
  ROT  2DUP  UM* // B D C A AC
  >R >R 2OVER    // B D C A B D
  ROT UM* >R >R  // B D C B
  UM* >R >R UM*  // BD
  0 R> R> R>     // BDL BDH. L H L
  SWAP >R 0 TUCK // BDL BDH. L. L.
  D+ D+ 0        // BDL BDH+ CY.
  R> R> 0 TUCK   // BDL BDH+ CY. H. H.
  D+ D+          // BDL BDH+ CY+ CY2
  R> R> D+ ;

Here is the source for DSQRT . It does not round.
Code:
CODE DSQRT  ( UQ -- UD )
   TYA  $FF ,X STA  8 # LDY
   BEGIN
      N 1- ,Y STA  DEY
   0< UNTIL
   $20 # LDY
   BEGIN
      1 ,X LDA
   0= WHILE
      0 ,X LDA  1 ,X STA
      3 ,X LDA  0 ,X STA
      2 ,X LDA  3 ,X STA
      5 ,X LDA  2 ,X STA
      4 ,X LDA  5 ,X STA
      7 ,X LDA  4 ,X STA
      6 ,X LDA  7 ,X STA
      DEY DEY DEY DEY
   0= UNTIL
      POPTWO JMP
   THEN
   BEGIN
      6 ,X ASL  7 ,X ROL
      4 ,X ROL  5 ,X ROL
      2 ,X ROL  3 ,X ROL
      0 ,X ROL  1 ,X ROL
      N    ROL  N 1+ ROL
      N 2+ ROL  N 3 + ROL
      $FF ,X ROL
      6 ,X ASL  7 ,X ROL
      4 ,X ROL  5 ,X ROL
      2 ,X ROL  3 ,X ROL
      0 ,X ROL  1 ,X ROL
      N    ROL  N 1+ ROL
      N 2+ ROL  N 3 + ROL
      $FF ,X ROL
      N 4 + ASL  N 5 + ROL
      N 6 + ROL  N 7 + ROL
      N 1-  ROL  SEC
      N 4 + ROL  N 5 + ROL
      N 6 + ROL  N 7 + ROL
      N 1-  ROL  SEC
      N     LDA  N 4 + SBC
      N 1+  LDA  N 5 + SBC
      N 2+  LDA  N 6 + SBC
      N 3 + LDA  N 7 + SBC
      $FF ,X LDA  N 1- SBC
      CS IF
         N     LDA  N 4 + SBC  N     STA
         N 1+  LDA  N 5 + SBC  N 1+  STA
         N 2+  LDA  N 6 + SBC  N 2+  STA
         N 3 + LDA  N 7 + SBC  N 3 + STA
         $FF ,X LDA  N 1- SBC  $FF ,X STA
         N 4 + LDA  2 # ORA  N 4 + STA
      THEN
      N 1- LSR
      N 7 + ROR  N 6 + ROR
      N 5 + ROR  N 4 + ROR  DEY
   0= NOT WHILE  // TOO FAR TO
   REPEAT        // BRANCH BACK
   N 4 + LDA  6 ,X STA
   N 5 + LDA  7 ,X STA
   N 6 + LDA  4 ,X STA
   N 7 + LDA  5 ,X STA
   POPTWO JMP
END-CODE



Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 20, 2022 1:45 am 
Offline

Joined: Wed Aug 21, 2019 6:10 pm
Posts: 217
GARTHWILSON wrote:
I can't think of any situation where STATE would be something other than 0 or FFFF. I would think that if it were, it'd be because something corrupted it, meaning it would be invalid anyway. If that happened, you'd probably have additional problems to worry about.


I can easily imagine a situation where STATE is not used by the outer interpreter, but is simply offered as a convenience for portable code, where STATE is always 0 or TRUE, but setting STATE doesn't actually DO anything ... when you CALL STATE, it infers the state, and puts the 0 or TRUE in the location that it returns.

Also in a context of support for porting standard code to a system, I can also imagine a situation where there are three states ... regular interpretation, regular compilation, and some special compilation state, where STATE for the special compilation state is 1 rather than TRUE.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 25, 2022 2:34 am 
Offline

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

I've changed the way WORD is defined in Fleet Forth.
Both versions use 'STREAM to obtain the address of the current position in the text stream and the remaining length. Here is the latest definition of 'STREAM .
Code:
: 'STREAM  ( -- ADR N )
   BLK @ ?DUP
   IF
      BLOCK B/BUF
   ELSE
      TIB #TIB @
   THEN
   >IN @
   OVER UMIN /STRING ;

Both use SKIP to skip leading occurrences of the delimiter and SCAN to scan for the delimiter at the end of the parsed text.
The new version of Fleet Forth's WORD is different in how it adjusts >IN . The old WORD saved the length returned by 'STREAM , the address returned by SKIP , and the address and length returned by SCAN . They were passed to the headerless word ADJUST in this order: address returned by SKIP , length returned by 'STREAM , address returned by SCAN , and length returned by SCAN . ADJUST calculated how far to move >IN without making it point further than one byte past the text stream. Even though ADJUST was headerless, it did have a name in the source used by the metacompiler.
For the old and new versions of WORD , as well as CHAR , when the source is a block, WORD will never leave >IN with a value larger than B/BUF ( 1024), otherwise >IN will never be left with a value larger than that in #TIB . Although >IN can be manually set to a larger value, doing so causes 'STREAM to return a size of zero for the remaining length of the text stream.

The new version of Fleet Forth's WORD does away with the headerless word ADJUST . The length returned by 'STREAM is added to >IN , pushing it just past the text stream. The length remaining returned by SCAN is decremented and the maximum of it and zero is subtracted from >IN .

The change to CHAR also did away with the need for ADJUST . CHAR takes a delimiter and returns an address and length for the parsed text. CHAR does not skip leading delimiters and the text stream can not be exhausted without an error condition since the delimiter must be found. The only place CHAR alters >IN is where the returned length plus one is added to >IN .
Here are the old versions of WORD and CHAR .
Code:
NH
2VARIABLE HISTORY
NH
: ADJUST  ( A1 L1 A2 L2 -- A1 CNT )
   DUP 0<> + NEGATE ROT +  \ adr1 adr2 len3
   >IN +!                  \ adr1 adr2
   OVER - ;                \ adr1 cnt
: WORD  ( C -- ADR )
   >R 'STREAM              \ adr1 len1
   BLK 2@ HISTORY 2!       \ save BLK and >IN
   TUCK R@ SKIP            \ len1 adr2 len2
   >R TUCK R> R> SCAN      \ adr2 len1 adr3 len3
   ADJUST >HERE ;          \ adr2 cnt

: CHAR  ( C -- ADR CNT )
   DUP>R LIT [ HERE >A 0 , ] C!
   'STREAM 2DUP R>         \ adr1 len1 adr1 len1 c
   SCAN DUP 0=             \ adr1 len1 adr2 len2 flag
   [ HERE 3 + A> ! ]
   ABORT"   MISSING"
   ADJUST ;                \ adr1 cnt


Here are the new versions.
Code:
NH
2VARIABLE HISTORY
: WORD  ( C -- HERE )
   'STREAM                 \ c adr1 len1
   BLK 2@ HISTORY 2!       \ save BLK and >IN
   DUP >IN +!
   2PICK SKIP              \ c adr2 len2
   ROT 2PICK -ROT SCAN     \ adr2 adr3 len3
   1- 0 MAX NEGATE >IN +!  \ adr2 adr3
   OVER - >HERE ;          \ here

: CHAR  ( C -- ADR CNT )
   DUP>R LIT [ HERE >A 0 , ] C!
   'STREAM 2DUP R>         \ adr1 len1 adr1 len1 c
   SCAN 0=                 \ adr1 len1 adr2 flag
   [ HERE 3 + A> ! ]
   ABORT"   MISSING"
   NIP OVER -              \ adr2 cnt
   DUP 1+ >IN +! ;         \ adr2 cnt

The line:
Code:
   BLK 2@ HISTORY 2!       \ save BLK and >IN

saves the values of BLK and >IN in a headerless double variable HISTORY for use by WHERE , the word which displays where an error occurred.
The extra size of WORD and CHAR exactly offset the memory saved by removing the headerless word ADJUST ; however, there are fewer trips through NEXT with WORD and CHAR so they will be slightly faster.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 13, 2022 11:47 pm 
Offline

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

I've changed the definition for Fleet Forth's LOAD . Here is the old definition:
Code:
: LOAD  ( U -- )
   0 SWAP LINELOAD ;

And the new:
Code:
: LOAD  ( U -- )
   0 SWAP BRANCH
   [ ' LINELOAD >BODY , ] ; -2 ALLOT

This does not change the size of LOAD , nor will it make a noticeable speed improvement. It does save a cell on the return stack for each nesting of nested LOADs .
I've also changed the source for Fleet Forth's warm start routine from this:
Code:
HSUBR WARM
   $FF # LDX  TXS
   (WARM) JSR
   >FORTH
   FORTH DEFINITIONS
   ." {REV}WARM START"
   ABORT ; -2 ALLOT

To this:
Code:
HSUBR WARM
   $FF # LDX  TXS
   (WARM) JSR
   >FORTH
   FORTH DEFINITIONS
   ." {REV}WARM START"
   QUIT ; -2 ALLOT

Note: {REV} is the reverse print character in the C64 PETSCII. A carriage return clears the reverse print mode.
Here is the definition for Fleet Forth's ABORT
Code:
: ABORT  ( -- )
   SINGLE ERR SP! AP!
   QUIT ; -2 ALLOT

Since the stacks are cleared and multitasking is disabled in the subroutine called by the warm start and cold start routines, there is no need to go to ABORT rather than QUIT in the warm start routine. This also avoids executing the deferred word ERR during a warm start which could have been initiated because ERR was set to a bad vector.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jul 19, 2022 12:40 am 
Offline

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

Back near the end of 2020 I presented the source code for Fleet Forth's new (ABORT") , which is so much faster than the old version when there is no error.
Code:
CODE (ABORT")  ( F -- )
   0 ,X LDA,  1 ,X ORA,
   0= IF,
      IP )Y LDA,  SEC,
      IP ADC,  IP STA,
      CS IF,  IP 1+ INC,  THEN,
      POP JMP,
   THEN,
   >FORTH
   WHERE CR R@ S?
   ABORT ;
   -2 ALLOT

The following snippet of code skips Fleet Forth's instruction pointer, IP , over an inline counted string.
Code:
   IP )Y LDA,  SEC,
   IP ADC,  IP STA,
   CS IF,  IP 1+ INC,  THEN,

There are two other words in Fleet Forth which skip over an inline string. They are (.") and (") .
Code:
: (.")  ( -- )
   R> COUNT 2DUP + >R TYPE ;
: (")  ( -- ADR )
   R> DUP COUNT + >R ;

Fleet Forth's kernel can be made smaller by taking the string skipping code out of (ABORT") and placing it in (") .
Code:
: (")  ( -- ADR )
   R@
   >ASSEM
   IP )Y LDA  SEC
   IP ADC  IP STA
   CS IF  IP 1+ INC  THEN
   NEXT JMP  END-CODE
: (.")  ( -- )
   R@ COUNT TYPE
   BRANCH
   [ ' (") >BODY 2+ , ] ; -2 ALLOT

The new (") is six bytes bigger and the new (.") is four bytes smaller.
The newest (ABORT") is twelve bytes smaller for a net savings of ten bytes.
Code:
CODE (ABORT")  ( F -- )
   INX  INX
   $FE ,X LDA  $FF ,X ORA
   ' (") >BODY 4 +  0= BRAN
   >FORTH
   WHERE  CR R> S?
   ABORT ; -2 ALLOT

(ABORT") is still fast. When there is no error, this version of (ABORT") should be two cycles faster. The branch does not cross a page boundary, my metacompiler reports page boundary crossings. I get a print file of the metacompiler messages by typing LOGGER before loading the kernel source.

There is also this code in ?BRANCH
Code:
      LABEL 2.IP.+!
      CLC
      IP LDA  2 # ADC  IP STA
      NEXT CS NOT BRAN
      IP 1+ INC
      NEXT 0= NOT BRAN  // ALWAYS

which skips IP over a cell.
Note: LABEL creates a label in the metacompiler's host vocabulary with the present value of THERE , the target's HERE , as its value. It does not increase the size of the target in any way.
This code fragment, 2.IP.+! can also be used by (IS) , the word compiled by IS , and COMPILE .
The original source.
Code:
: (IS)
   R> DUP 2+ >R @ >BODY ! ;
: COMPILE
   ?COMP R> DUP 2+ >R @ , ;

And the new.
Code:
: (IS)  ( -- )
   R@ @ >BODY !
   LABEL SKIP.CELL
   >ASSEM
   2.IP.+! JMP  END-CODE
: COMPILE
   ?COMP  R@ @ ,  BRANCH
   [ SKIP.CELL , ] ; -2 ALLOT

The new (IS) is three bytes smaller and the new COMPILE is four bytes smaller.


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 16, 2022 2:35 am 
Offline

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

I mentioned in this post that I was going to write an experimental kernel. I've written the experimental kernel and I like it. Here is the source for the following words:
?EXIT 0EXIT ?LEAVE (LOOP) ?BRANCH

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

CODE (LOOP)
   XSAVE STX  TSX  $101 ,X INC
   0= IF  // BRANCHING OUT OF WORD
   SEC  TYA
   LABEL I.HI+A
   $102 ,X ADC  $102 ,X STA
   VS IF  // BRANCHING OUT OF WORD
   XSAVE LDX
   A>CS A>CS THEN
   LABEL LEAVE.BODY
   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   CS>A  CS>A
   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 ?BRANCH  ( F -- )
   INX  INX
   $FE ,X LDA  $FF ,X ORA
   0= NOT IF
      LABEL 2.IP.+!
      CLC
      IP LDA  2 # ADC  IP STA
      NEXT CS NOT BRAN
      IP 1+ INC
      NEXT 0= NOT BRAN  // ALWAYS
      A>CS THEN  A>CS THEN
      LABEL XBRANCH
      XSAVE LDX
   THEN
   IP )Y LDA  PHA  INY
   IP )Y LDA  IP 1+ STA
   PLA  IP STA
   NEXT 2+ JMP  END-CODE

The label XBRANCH is no longer needed since it is now only used in the phrase XBRANCH 2+ . I will remove it and add a label just under the line with XSAVE LDX . This new label will be BRANCH.BODY . Of course, I'll need to change the two occurrences of XBRANCH 2+ to BRANCH.BODY .

In Fleet Forth, an item of control flow data consists of an address and a security number. The words which supply the address and security number are
>MARK <MARK
the words which use the address and security number are
>RESOLVE <RESOLVE
The control flow security is to make sure that a >MARK is matched with a >RESOLVE and a <MARK is matched with a <RESOLVE . These two conditions are to make sure that branches are properly resolved, avoiding an upcoming system crash. As long as they are met, control flow words can be used in any way the programmer sees fit.

The word CS>A copies one item of control flow data to the auxiliary stack and the word A>CS copies one item of control flow data from the auxiliary stack.
Using the auxiliary stack to temporarily hold the control flow data makes it easier to write branches out of the words ?EXIT 0EXIT and ?LEAVE and into the body of (LOOP) . It also makes it easier to write two branches out of (LOOP) and into the body of ?BRANCH (really into the part that has the code for BRANCH ).

Here is the source for the words BRANCH LEAVE and EXIT , which have no bodies.
Code:
CODE BRANCH  ( -- )
   -2 ALLOT XBRANCH 2+ ,
END-CODE
CODE LEAVE  ( -- )
   -2 ALLOT  LEAVE.BODY ,
END-CODE
CODE EXIT  ( -- )
   -2 ALLOT  EXIT.BODY ,
END-CODE

With the new kernel, EXIT and LEAVE fall through to NEXT because their code is in the body of (LOOP) .
(LOOP) falls through to NEXT when the DO LOOP terminates.

Here is the new source for LIT .
Code:
CODE LIT  ( -- W )
   DEX  DEX
   IP )Y LDA  0 ,X STA  INY
   IP )Y LDA  1 ,X STA
   2.IP.+! JMP  END-CODE

2.IP.+! is a metacompiler label for the address in ?BRANCH which, as the label name implies, adds two to IP .

Here is the new source for CLIT .
Code:
CODE CLIT  ( -- B )
   IP )Y LDA
   IP INC
   0= IF  IP 1+ INC  THEN
   AYPUSH JMP
// SETUP SETS CARRY AS SIDE EFFECT
LABEL SETUP
   .A ASL  N 1- STA
   BEGIN
      0 ,X LDA  N ,Y STA
      INX  INY  N 1- CPY
   0= UNTIL
   0 # LDY
   RTS  END-CODE

Placing the code for SETUP right after CLIT was done as a convenience (or laziness on my part). I could just as well have placed END-CODE after the jump to AYPUSH with HSUBR SETUP (headerless subroutine) used rather than LABEL SETUP .

LIT and CLIT are used in LITERAL .
Code:
: LITERAL  ( N -- )
   DUP SPLIT NIP
   IF  COMPILE LIT , EXIT  THEN
   COMPILE CLIT C, ; IMMEDIATE


I have removed the constants PUSH and PUT from Fleet Forth's assembler. Fleet Forth has AYPUSH to push a cell on the data stack with the low byte in the accumulator and high byte in the Y-register, and the word AYPUT to replace a cell on the data stack. If the high byte were in the accumulator, I would have named them YAPUSH and YAPUT to reflect the (low byte, high byte) order of the 16 bit cell.
It seemed awkward to me to have AYPUSH AYPUT as well as PUSH PUT in the assembler, almost like Fleet Forth's kernel was not a single unified design. With the new kernel, a jump to PUSH and PUT now cost three more clocks cycles, so I got rid of them.
If a code word needs them, the following code fragments can be defined.
Code:
SUBR PUSH  ( -- W )
   TAY  PLA
   AYPUSH JMP
END-CODE

SUBR PUT  ( -- W )
   TAY  PLA
   AYPUT JMP
END-CODE

These are used just like the constants PUSH and PUT in the FIG Forth assembler.

I have a disk of Blazin' Forth utilities ported to Fleet Forth. When I modified the words using PUSH and PUT to use AYPUSH and AYPUT , they were smaller. These words were a more natural fit for AYPUSH and AYPUT than PUSH and PUT .

The experimental kernel was slightly smaller until I saw how I could squeeze a few more cycles out of the code portion of BLOCK and made a few other speed/size trade offs before rebuilding once again. The experimental kernel is now about three bytes bigger than the other one.
I'm going to run a few more tests, maybe look for potential optimizations. My metacompiler reports where a branch crosses a page boundary, I'd like to minimize the occurrence of those. They're not so bad when the branch is not part of a loop, but I really don't like the extra cycle in a loop. As I said, I like this experimental kernel. It is Fleet Forth's new kernel.


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 30, 2022 12:49 am 
Offline

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

In this post I discussed Fleet Forth's WORD .
I think UMIN and 2PICK were the only non-standard words which I didn't define.
UMIN is the unsigned version of MIN .
Fleet Forth's 2PICK has the same stack effect as the phrase '2 PICK'.
Here is Fleet Forth's 2PICK
Code:
CODE 2PICK  ( N1 N2 N3 -- N1 N2 N3 N1 )
   4 ,X LDA  5 ,X LDY
   AYPUSH JMP  END-CODE

Fleet Forth's double number version of PICK is DPICK
As with Mosaic Forth's DPICK , it is zero based and copies the double number whose high cell is the Nth item on the data stack, not counting N. This double number could also be thought of as a pair of single numbers.
Code:
DPICK  ( D WN-1 . . . W0 +N -- D WN-1 . . . W0 D )

Here is another way to look at it. Not counting N, PICK skips the top N numbers on the stack and copies the next one to push onto the stack.
2PICK skips the top number, the next to top number and copies the third number to push onto the stack.
DPICK also skips the top N numbers on the stack but it copies two cells ( a double or a pair of singles ) to push onto the stack.


Top
 Profile  
Reply with quote  
PostPosted: Sat Sep 03, 2022 3:07 pm 
Offline

Joined: Wed Aug 21, 2019 6:10 pm
Posts: 217
In xForth I use THIRD for what you have called 2PICK. FOURTH is what would be 3PICK in that naming system, but I stop at THIRD, so the verbal confusion of FOURTH and FORTH is not an issue.


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 19 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: