Jump to content
IGNORED

TurboForth to Assembly ??


Shift838

Recommended Posts

So I thought I would try my hand at TurboForth and I am getting the concepts down.

 

My question, is can the source code of my program be compiled into Assembly so that the program can be ran without the TurboForth cartridge, like EA option 3 or EA option 5 ?

 

If so, how?

 

 

  • Thanks 1
Link to comment
Share on other sites

I do know that fbforth and turboforth both have the ability to let you code in assembly as they have most of the 9900 assembler code as words that allows for assembler execution.

Example, in TF registers are set as

"R1," instead of "R1" and use words such as "SOC," instead of "SOC".

Note the"," comma it may actually be at the beginning of the word instead of the end.

I can't remember off hand, and the manual explains this, but no labels exist since forth handles the code.

I've never heard of what you are asking for though.

Also, I think if it were converted it would have timing Problems as do other programs that get converted.

 

Edited by GDMike
Link to comment
Share on other sites

1 hour ago, Shift838 said:

So I thought I would try my hand at TurboForth and I am getting the concepts down.

 

My question, is can the source code of my program be compiled into Assembly so that the program can be ran without the TurboForth cartridge, like EA option 3 or EA option 5?  If so, how?

 

The simple answer is no. Without a compiler written for that purpose, the best you can do is to compile/interpret your source code with Turboforth and BSAVE it for a later BLOAD that loads into memory the binary saved with BSAVE , which, of course, still requires the cartridge. The Forth code is compiled to a list of executable address that require the Forth Inner Interpreter to run. The cartridge contains all of the executable code those execution addresses reference. In order to actually do what you ask, a compiler such as Harry Wilhem (@senior_falcon) wrote for Basic would need to be developed for Turboforth.

 

...lee

  • Thanks 2
Link to comment
Share on other sites

5 hours ago, Lee Stewart said:

 

The simple answer is no. Without a compiler written for that purpose, the best you can do is to compile/interpret your source code with Turboforth and BSAVE it for a later BLOAD that loads into memory the binary saved with BSAVE , which, of course, still requires the cartridge. The Forth code is compiled to a list of executable address that require the Forth Inner Interpreter to run. The cartridge contains all of the executable code those execution addresses reference. In order to actually do what you ask, a compiler such as Harry Wilhem (@senior_falcon) wrote for Basic would need to be developed for Turboforth.

 

...lee

 

Or one could use a Forth Cross-compiler. 

 

@shift838

This is a Forth compiler that generates code in separate memory space or even to disk if that's all there is. That memory image becomes a binary program when saved to disk.

Forth cross-compilers are really cool from the intellectual standpoint , once you get them going but not for the faint of heart to create. It took me quite a while to get mine running.

 

I have a Forth Cross-Assembler now.  If you understand Forth's internals a now, you might (or not) want to study how it works.

In theory, with the cross assembler you could assembler an entire Forth system with only what you needed and then write a game in that new Forth.

The game would exist as a memory image that you could save as EA5 and run.  

 

This kind of stuff is probably best described as "black-belt" level Forth but I am happy to help if you are interested.

It could be done on Turbo Forth as well.  It would not take much of a preamble to make the turbo-forth assembler become a cross-assembler.

 

Note:

I have been thinking about improving my cross-compiler so that it more like normal Forth.

It can never be exactly like normal Forth but I could remove a few warts here and there for other people to use it. :) 

 

 

  • Like 2
Link to comment
Share on other sites

By way of example , here is the code for a Hello world program, written in Camel99 Forth  Cross-Assembler

Spoiler

\  Cross compiling program demo

NEEDS NEW. FROM DSK1.CROSS99

MARKER /XASMDEMO

HEX
       NEW.
       A000 ORIGIN.

SUB: WMODE
       R0 4000  ORI,
       R0 SWPB,
       0 LIMI,
       R0 8C02 @@ MOVB,
       R0 SWPB,
       R0 8C02 @@ MOVB,
       RET,
;SUB

SUB: VWRITE  ( CPU-addr VDP-addr cnt -- )
       WMODE @@ BL,
       BEGIN, TOS DEC,
       OC WHILE,
            R1 *+  8C00 @@ MOVB,
       REPEAT,
       2 LIMI,
       TOS POP,
       RET,
;SUB

L: A$  S" Hello World!" TEXT, \ compiles a byte counted string

\ main program.........
PROG: XASMTEST
     8300 LWPI,   \ Forth workspace
     SP FF00 LI,  \ set data stack
     RP FE00 LI,  \ set return stack

\ set up to write string
     A$ @@ TOS MOVB,    \ get count byte to TOS
     TOS SWPB,          \ swap byte to other side
     R1  A$ 1+ LI,      \ start of text to R1
     R0 CLR,            \ VDP screen address to R0
     VWRITE @@ BL,

\ delay
     TOS FFFF LI,
     BEGIN,
       R1 16 SRL,
       R1 16 SLA,
       TOS DEC,
     EQ UNTIL,

\ return to main menu
     83E0 LWPI,
     R0 CLR,
     R0 837C @@ MOV,
     RT,
END.

CR .( Saving file ) S" DSK3.HELLO" 2DUP TYPE  SAVE-EA5

CR .( Program size = ) BYTESUSED DECIMAL . .( bytes)

 

 

And here is the source for the entire cross-assembler including Assembler directives.

 

Spoiler

CR .( CROSS ASSEMBLER for Camel99 Forth )
( *NOTE:                                              )
(        compare instruction has been changed to CMP, )
(        to remove name conflict with C,              )
(        change A, and S, to ADD, SUB,                )

NEEDS CASE  FROM DSK1.CASE

: XASM99 ;

VARIABLE TDP   \ "target dictionary point"

\ set where the Cross-assembler puts its code
: ORG   ( addr -- ) TDP ! ;

\ Target versions of HERE and ALLOT
: THERE  ( -- addr) TDP @ ;
: TALLOT ( n -- )   TDP +! ;

\ integer and byte "Target" compilers
: T,     ( n -- )   THERE !  2 TALLOT ;
: TC,    ( c -- )   THERE C! 1 TALLOT ;


\ ===================================================
CR .( TI-99 Cross Assembler V 0.1 ...)

CR .( Loading at) DP @ HEX U.

DECIMAL
 0 CONSTANT  R0    1 CONSTANT  R1
 2 CONSTANT  R2    3 CONSTANT  R3
 4 CONSTANT  R4    5 CONSTANT  R5
 6 CONSTANT  R6    7 CONSTANT  R7
 8 CONSTANT  R8    9 CONSTANT  R9
10 CONSTANT R10   11 CONSTANT R11
12 CONSTANT R12   13 CONSTANT R13
14 CONSTANT R14   15 CONSTANT R15

HEX
: ADDRESS? ( n -- ?) DUP 1F > SWAP 30 < AND ;

: GOP'     OVER ADDRESS?        \ address or register?
           IF   + T, T,         \ compile instruction & address
           ELSE + T,            \ compile register
           THEN ;

: GOP      CREATE , DOES> @ GOP' ;

0440 GOP B,     0680 GOP BL,    0400 GOP BLWP,
04C0 GOP CLR,   0700 GOP SETO,  0540 GOP INV,
0500 GOP NEG,   0740 GOP ABS,   06C0 GOP SWPB,
0580 GOP INC,   05C0 GOP INCT,  0600 GOP DEC,
0640 GOP DECT,  0480 GOP X,

: GROP     CREATE , DOES> @ SWAP 40 * + GOP' ;

2000 GROP COC,  2400 GROP CZC,  2800 GROP XOR,
3800 GROP MPY,  3C00 GROP DIV,  2C00 GROP XOP,

: GGOP     CREATE ,
           DOES> @ SWAP DUP ADDRESS?
                 IF   40 * + SWAP >R GOP' R> T,
                 ELSE 40 * + GOP'  THEN ;
HEX
A000 GGOP ADD,  B000 GGOP ADDB, 8000 GGOP CMP, 9000 GGOP CMPB,
6000 GGOP SUB,  7000 GGOP SUBB, E000 GGOP SOC, F000 GGOP SOCB,
4000 GGOP SZC,  5000 GGOP SZCB, C000 GGOP MOV, D000 GGOP MOVB,

: 0OP     CREATE ,  DOES> @ T, ;

0340 0OP IDLE,   0360 0OP RSET,  03C0 0OP CKOF,
03A0 0OP CKON,   03E0 0OP LREX,  0380 0OP RTWP,

: ROP     CREATE , DOES> @ + T, ;
02C0 ROP STST,
02A0 ROP STWP,

: IOP     CREATE , DOES> @ T, T, ;
02E0 IOP LWPI,
0300 IOP LIMI,

: RIOP    CREATE , DOES> @ ROT + T, T, ;
0220 RIOP AI,
0240 RIOP ANDI,
0280 RIOP CI,
0200 RIOP LI,
0260 RIOP ORI,

: RCOP    CREATE , DOES> @ SWAP 10 * + + T, ;
0A00 RCOP SLA,
0800 RCOP SRA,
0B00 RCOP SRC,
0900 RCOP SRL,

CR .( jump instructions)
: DOP     CREATE ,   DOES> @ SWAP 00FF AND OR T, ;
1300 DOP JEQ,  1500 DOP JGT,  1B00 DOP JH,   1400 DOP JHE,
1A00 DOP JL,   1200 DOP JLE,  1100 DOP JLT,  1000 DOP JMP,
1700 DOP JNC,  1600 DOP JNE,  1900 DOP JNO,  1800 DOP JOC,
1C00 DOP JOP,  1D00 DOP SBO,  1E00 DOP SBZ,  1F00 DOP TB,

: GCOP    CREATE , DOES> @ SWAP 000F AND 40 * + GOP' ;

3000 GCOP LDCR,
3400 GCOP STCR,
HEX
\ Wycove assembler register syntax:
: @@        020    ;  \ symbolic addressing
: **        010 +  ;  \ indirect addressing
: *+        030 +  ;  \ indirect addressing, auto-increment
: ()        20  +  ;  \ indexed addressing

CR .( Jump tokens) \ for use with CJMP
HEX
 1 CONSTANT GTE     \ GT OR EQUAL
 2 CONSTANT HI      \ JMP IF HI
 3 CONSTANT NE      \ NOT equal
 4 CONSTANT LO      \ jmp if low
 5 CONSTANT LTE     \ jmp if less than or equal
 6 CONSTANT EQ      \ jmp if equal
 7 CONSTANT OC      \ jmp on carry flag set
 8 CONSTANT NC      \ jmp if no carry flag set
 9 CONSTANT OO      \ jmp on overflow
 A CONSTANT HE      \ jmp high or equal
 B CONSTANT LE      \ jmp if low or equal
 C CONSTANT NP      \ jmp if no parity ?
 D CONSTANT LT      \ jmp if less than
 E CONSTANT GT      \ jmp if greater than
 F CONSTANT NO      \ jmp if no overflow
10 CONSTANT OP      \ jmp if ODD parity

: CJMP CASE
         LT OF 1101 T, 0 ENDOF
         GT OF 1501 T, 0 ENDOF
         NO OF 1901 T, 0 ENDOF
         OP OF 1C01 T, 0 ENDOF
         DUP 0< OVER 10 > ABORT" IF, BAD jump token"
       ENDCASE >< 1000 + T, ;

CR .( Structured branching and looping )
: IF,
        ?EXEC ( only useable in immediate mode)
         CJMP THERE  2-  42 ; IMMEDIATE

: ENDIF,
        ?EXEC
        42 ?PAIRS
        THERE OVER - 2- 2/ SWAP CHAR+ C! ; IMMEDIATE

: ELSE,
        ?EXEC
        42 ?PAIRS
        0  CJMP THERE 2- SWAP
        42 POSTPONE ENDIF,  42 ; IMMEDIATE

: BEGIN,
        ?EXEC
        THERE 41 ; IMMEDIATE

: UNTIL,
        ?EXEC
        SWAP 41 ?PAIRS
        CJMP THERE - 2/ 00FF AND
        THERE 1- C! ; IMMEDIATE

: AGAIN,
        ?EXEC
        0 POSTPONE UNTIL, ; IMMEDIATE

: REPEAT,
        ?EXEC
        >R >R    POSTPONE AGAIN,
        R> R> 2- POSTPONE ENDIF, ; IMMEDIATE

: WHILE,
        ?EXEC
        POSTPONE IF,  CELL+ ; IMMEDIATE

CR .( Pseudo instructions)
: RT,     ( -- )  R11 ** B, ;
: NOP,    ( -- )  0 JMP, ;
: NEXT,   ( -- )  R10 **  B, ;  \ 045A T,  ;  \ CAMEL99 NEXT: B *R10


CR CR .( Cross Assembler loaded)
HEX

 

 

Edit: Forgot this file which is the directives and stuff for saving the EA5 file.

 

Spoiler

CR .( Native code cross compiler  B Fox May 2020)
\ creates a binary program E/A 5 format

NEEDS DUMP      FROM DSK1.TOOLS
NEEDS THERE     FROM DSK1.XASM99
NEEDS MARKER    FROM DSK1.MARKER
NEEDS MALLOC    FROM DSK1.MALLOC
NEEDS R/W       FROM DSK1.ANSFILES
NEEDS SAVE-FILE FROM DSK1.LOADSAVE

MARKER CROSS99

HEX
2050 H !  \ reset Forth HEAP in low ram

1000 MALLOC CONSTANT HEADORG

HEADORG 3 CELLS + CONSTANT CODEORG

: NEW. ( -- )
       HEADORG TDP !
       THERE 2000 0FF FILL    \ erase target memory
\ create dummy ti-files header in target memory space
       0000 T,      \ multi-file flag
       0000 T,      \ program size
       0000 T,      \ load address
\ *all programs shall have a branch and address as 1st instruction
       0460 T,      \ branch instruction
       0000 T,  ;   \ address we branch to

: ]HEADER ( n ndx -- addr[n]) CELLS HEADORG + ; \ header as cell array

: MULTI!   ( ? -- )   0 ]HEADER ! ;

: SIZEFIELD ( -- addr) 1 ]HEADER ; \ size field in header
: SIZE@     ( -- n ) SIZEFIELD @ DUP 0= ABORT" Program size not set" ;

: LOADFIELD ( addr -- ) 2 ]HEADER ;
: LOAD@     ( addr -- ) LOADFIELD @ DUP 0= ABORT" LOAD address not set" ;

\ cross compiler extensions
VARIABLE AORG
HEX  
\ set cross-compiler org variable and store in file header
: ORIGIN. ( addr -- ) DUP AORG ! LOADFIELD ! ;
: ORG@    ( -- addr ) AORG @ DUP 0= ABORT" Program ORIGIN not set" ;

: BOOTFIELD ( -- addr) 4 ]HEADER ; \ boot field in the header
: BYTESUSED   ( -- n )   TDP @ HEADORG - ;

HEX
\ save program to file
: >VDPBUFF   ( addr -- ) 1000 SIZE@ VWRITE ;
: SAVE-EA5  ( file$ len -- ) HEADORG >VDPBUFF 1000 SIZE@ 13 SAVE-FILE ;

CR .( Forth VM support)
DECIMAL
4 CONSTANT TOS
: (TOS)     TOS () ;
: *TOS      TOS ** ;
: *TOS+     TOS *+ ;

6 CONSTANT SP
: (SP)      SP () ;
: *SP       SP ** ;
: *SP+      SP *+ ;
\ PUSH & POP to data stack
: PUSH,    ( src -- )  SP DECT,  *SP  MOV, ;    \ 10+18 = 28  cycles
: POP,     ( dst -- )  *SP+      SWAP MOV, ;    \ 22 cycles

7 CONSTANT RP    \ R11 is also 9900 LINK register
: (RP)      RP () ;
: *RP       RP ** ;
: *RP+      RP *+ ;
\ PUSH & POP to return ttack
: RPUSH,   ( src -- ) RP DECT,  *RP   MOV, ;
: RPOP,    ( dst -- ) *RP+      SWAP  MOV, ;

8 CONSTANT W
: (W)       W ()  ;
: *W        W **  ;
: *W+       W *+  ;

: *R10      R10 ** ;
: *R11      R11 ** ;

: RELOCATE ( Taddr -- addr') CODEORG - LOAD@ +  ;

\ create a label in HOST Forth
\ Returns a relocated TARGET address when executed
: L:    CREATE  THERE ,     DOES> @ RELOCATE ;

\ nestable sub-routines  ** MUST END WITH RET, **
: SUB:  ( -- ) CREATE  !CSP  THERE ,  R11 RPUSH,   DOES> @ RELOCATE ;
: RET,  ( -- ) R11 RPOP,  RT, ; \ nestable return psuedo-instruction
: ;SUB  ( -- ) ?CSP ;

: EVEN.   TDP @ ALIGNED TDP ! ;

: TEXT, ( c-addr u -- ) THERE OVER 1+ TALLOT PLACE  EVEN. ;

: PROG: ( -- <label> )
       CREATE !CSP
               THERE DUP ,           \ DUP & record code location
               RELOCATE BOOTFIELD !  \ also put it in program header

       DOES> @ RELOCATE ;            \ Runtime: return relocated address

: END.  ?CSP
        BYTESUSED DUP 2000 > ABORT" Prog > 8K"
        SIZEFIELD !  ;


 

 

  • Like 1
Link to comment
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.
Note: Your post will require moderator approval before it will be visible.

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...