Jump to content
TheBF

Machine Forth OMG

Recommended Posts

For the curious this is the same program as previous except it uses a FOR NEXT loop structure which is just a down-counter with the index held on the return stack.

This the output code with comments. You can see how the 9900 instructions map onto Forth quite well.

 

Spoiler
2018  0646  dect R6               ; 3000 #  ( pushes R4 accumulator 1st)  
201A  C584  mov  R4,*R6     
201C  0204  li   R4,>3000         
2020  0647  dect R7        
2022  C5C4  mov  R4,*R7           ; FOR  ( loop index on return stack)
2024  C136  mov  *R6+,R4          ; DROP
2026  0646  dect R6               ; AAAA #   
2028  C584  mov  R4,*R6           
202A  0204  li   R4,>AAAA         
202E  0646  dect R6               ; DUP
2030  C584  mov  R4,*R6           
2032  C204  mov  R4,R8            ; SWAP
2034  C116  mov  *R6,R4               
2036  C588  mov  R8,*R6          
2038  0646  dect R6               ; OVER
203A  C584  mov  R4,*R6           
203C  C126  mov  @>0002(R6),R4  
2040  06A0  bl   @>2004           ; CALL ROT     
2044  C136  mov  *R6+,R4          ; DROP      
2046  0646  dect R6               ; DUP   
2048  C584  mov  R4,*R6                
204A  0556  inv  *R6              ; AND     
204C  4136  szc  *R6+,R4               
204E  0646  dect R6               ; DUP      
2050  C584  mov  R4,*R6                
2052  E136  soc  *R6+,R4          ; OR     
2054  0646  dect R6               ; DUP      
2056  C584  mov  R4,*R6                
2058  2936  xor  *R6+,R4          ; XOR       
205A  0584  inc  R4               ; 1+
205C  0604  dec  R4               ; 1- 
205E  05C4  inct R4               ; 2+    
2060  0644  dect R4               ; 2-      
2062  0A14  sla  R4,1             ; 2*    
2064  0814  sra  R4,1             ; 2/     
2066  0504  neg  R4               ; NEGATE     
2068  0744  abs  R4               ; ABS      
206A  A136  a    *R6+,R4          ; +     
206C  0646  dect R6               ; 2 #     
206E  C584  mov  R4,*R6                
2070  0204  li   R4,>0002              
2074  C0F6  mov  *R6+,R3          ; *      
2076  38C4  mpy  R4,R3                 
2078  C136  mov  *R6+,R4          ; DROP      
207A  0617  dec  *R7              ; NEXT     
207C  18D4  joc  >2026                 
207E  05C7  inct R7                    
2080  045A  b    *R10             ; NEXT,  (return to ITC Forth)     
         

 

 

Share this post


Link to post
Share on other sites
14 hours ago, TheBF said:

For the curious this is the same program as previous except it uses a FOR NEXT loop structure which is just a down-counter with the index held on the return stack.

This the output code with comments. You can see how the 9900 instructions map onto Forth quite well.

 

  Reveal hidden contents

2018  0646  dect R6               ; 3000 #  ( pushes R4 accumulator 1st)  
201A  C584  mov  R4,*R6     
201C  0204  li   R4,>3000         
2020  0647  dect R7        
2022  C5C4  mov  R4,*R7           ; FOR  ( loop index on return stack)
2024  C136  mov  *R6+,R4          ; DROP
2026  0646  dect R6               ; AAAA #   
2028  C584  mov  R4,*R6           
202A  0204  li   R4,>AAAA         
202E  0646  dect R6               ; DUP
2030  C584  mov  R4,*R6           
2032  C204  mov  R4,R8            ; SWAP
2034  C116  mov  *R6,R4               
2036  C588  mov  R8,*R6          
2038  0646  dect R6               ; OVER
203A  C584  mov  R4,*R6           
203C  C126  mov  @>0002(R6),R4  
2040  06A0  bl   @>2004           ; CALL ROT     
2044  C136  mov  *R6+,R4          ; DROP      
2046  0646  dect R6               ; DUP   
2048  C584  mov  R4,*R6                
204A  0556  inv  *R6              ; AND     
204C  4136  szc  *R6+,R4               
204E  0646  dect R6               ; DUP      
2050  C584  mov  R4,*R6                
2052  E136  soc  *R6+,R4          ; OR     
2054  0646  dect R6               ; DUP      
2056  C584  mov  R4,*R6                
2058  2936  xor  *R6+,R4          ; XOR       
205A  0584  inc  R4               ; 1+
205C  0604  dec  R4               ; 1- 
205E  05C4  inct R4               ; 2+    
2060  0644  dect R4               ; 2-      
2062  0A14  sla  R4,1             ; 2*    
2064  0814  sra  R4,1             ; 2/     
2066  0504  neg  R4               ; NEGATE     
2068  0744  abs  R4               ; ABS      
206A  A136  a    *R6+,R4          ; +     
206C  0646  dect R6               ; 2 #     
206E  C584  mov  R4,*R6                
2070  0204  li   R4,>0002              
2074  C0F6  mov  *R6+,R3          ; *      
2076  38C4  mpy  R4,R3                 
2078  C136  mov  *R6+,R4          ; DROP      
207A  0617  dec  *R7              ; NEXT     
207C  18D4  joc  >2026                 
207E  05C7  inct R7                    
2080  045A  b    *R10             ; NEXT,  (return to ITC Forth)     
         

 

 

 

Is it usual for the FOR limit to not be consumed?

 

...lee

  • Like 1

Share this post


Link to post
Share on other sites
2 hours ago, Lee Stewart said:

 

Is it usual for the FOR limit to not be consumed?

 

...lee

The DROP following FOR is doing that remembering that this system uses R4 as a cache for the top of stack.

So DROP always refills R4 from the memory stack.

 

The return stack works as a normal stack in memory so the inct R7 is removing the limit from the return stack 

207A  0617  dec  *R7              ; NEXT     
207C  18D4  joc  >2026                 
207E  05C7  inct R7             

Unless you have found something I am completely missing, which has happened before, that is how I think it should work. :) 

 

 

  • Haha 1

Share this post


Link to post
Share on other sites
2 hours ago, GDMike said:

Not a bad thing to happen 😜.

 

Indeed not. Lee has found so many bugs in my code I want to start calling him "Raid". :)

 

  • Haha 2

Share this post


Link to post
Share on other sites
Just now, TheBF said:

Indeed not. Lee has found so many bugs in my code I want to start calling him "Raid". :)

 

Mine to, no matter what I was doing. The Eyes have it with him. Lol

  • Haha 1

Share this post


Link to post
Share on other sites

POP/PUSH Optimization

 

This is something that I know should be a part of a good Forth native code compiler but I always created bugs when I tried it in the past.

I think I have this working so I am going to explain again to myself and anyone who cares to read about it just to confirm my logic.

 

When you run a Forth machine with a cache register for the top of stack element there are many Forth instructions that end with an instruction to refill the cache register.  This is effectively a DROP function in the Forth machine because you are POPPING the stack into the register.

 

Other Forth instructions need to use the cache register when they start, so they push the cache register onto the stack in memory first thing.

This is effectively a DUP instruction on the Forth machine.

 

IF a Forth instruction that ends with a DROP is followed immediately by an instruction that does a DUP that is three useless instructions that just thrash the top element of the stack.  Three extra instructions on the 9900 can really slow things down, especially inside a loop. 

The solution was a "SMARTDUP" and I think I have the logic correct this time.

 

Spoiler
\ ************* optimizable operations ***************
COMPILER
: D=    ( d d -- ?)  ROT = -ROT = AND ;
: 1LOOKBACK ( n -- ? ) THERE 1 CELLS - @ = ;
: 2LOOKBACK ( d -- ? ) THERE 2 CELLS - [email protected] D= ;

: REMOVE ( n -- )  CELLS NEGATE TALLOT ;  \ remove n cells from program
: ADUP     C584 0646 ;  \ DUP is 2 instructions, 4 bytes

: !,    TOS SWAP @@ MOV, ;
: DROP,   TOS POP, ;
: DUP,    TOS PUSH, ;
: C!,     TOS SWPB, TOS SWAP @@ MOVB, ;

\ POP/PUSH optimization:
\ Some words refill the stack with DROP. If the next word does a DUP
\ we should not have compiled the DROP, so SMARTDUP removes it.
COMPILER
: SMARTDUP
        OPTIMIZER @
        IF
          0C136 1LOOKBACK \ did we just emit a drop?
          IF  1 REMOVE    \ YES, so remove it
          ELSE DUP,       \ NO, so we must DUP
          THEN

        ELSE
           DUP,           \ regular DUP is compiled
        THEN ;

 TARGET
 : !  ( n variable --)
 [CC]
       OPTIMIZER @
       IF
          ADUP 2LOOKBACK   \ look back for ADUP
          IF   2 REMOVE  !,
          ELSE !, DROP,    \ un-optimized
          THEN
       ELSE
          !, DROP,         \ un-optimized
       THEN ;
TARGET
 : C!   ( c variable --)
 [CC]
       OPTIMIZER @
       IF
          ADUP 2LOOKBACK  \ look back for DUP
          IF    2 REMOVE C!,  \ optimized
          ELSE  C!, DROP,  \ un-optimized
          THEN
       ELSE
          C!, DROP,   \ un-optimized
       THEN ;

 

 

Using these concepts I also optimized ! and C! for expressions like :

1234 DUP X !

 Since ! (store)  consumes both of its arguments it always ends with a DROP.

I look back 2 cells in the program and if I find a DUP  I can remove that dup since 1234 is sitting in R4 ready to go.

And since I removed the DUP I don't need the DROP after I store the number in X. 

 

* ADUP in the code has the instructions in reverse order to match the way [email protected] reads memory in 2LOOKBACK.

 

 

 

  • Like 3

Share this post


Link to post
Share on other sites

MACHFORTH is getting closer to being useful

 

This little program relocates the code to load at >A000 and it also steals the entire scratchpad for Forth stacks and workspace.

And it successfully saves the image to disk.

\ MFORTH DEMO #1b  Use new workspace and stacks, save binary program
\ If running on Classic99 you will see R4 counting down

\ This demo shows:
\ - compile to >A000 origin
\ - create workspace and both stacks in scratchpad memory
\ - saves a finished program that can RUN from E/A Option 5

COMPILER
   NEW.
   HEX A000 ORIGIN.

INCLUDE DSK2.BYE  \ a little code to exit program

TARGET
PROG: DEMO1
       0 LIMI,      \ disable interrupts to take over the machine
       8300 WORKSPACE
       8380 RSTACK
       8400 DSTACK
       FFFF #
       BEGIN
           1-       \ decrement data stack
       -UNTIL       \ -UNTIL DOES NOT consume the stack parameter
       DROP         \ clean up the stack
       BYE          \ Return to TI title screen
END.

SAVE DSK2.DEMO1C

 

  • Like 4

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...