/foco65

Forth cross-compiler targeting 6502 processors.

Primary LanguagePythonGNU General Public License v3.0GPL-3.0

foco65

Forth cross-compiler targeting 6502 processors. Outputs xasm compatible assembly source code containing Forth runtime and compiled user program.

Runtime

Generated Forth runtime is 16-bit indirect-threaded.

Parameter stack is full-descending and addressed by X register. Address and size of the parameter stack are by default $600 and 256 respectively and are user-configurable.

Hardware stack is used as return stack.

The runtime uses 12 bytes on zero page: 2-byte instruction pointer ip and 5 2-byte work registers: w, z, cntr, tmp, tmp2 which may be used in user-defined words (note than on every word entry these registers' contents are undefined).

On entry runtime initializes instruction pointer and enters user-defined word main which is supposed to never exit (i.e. contain an infinite loop).

Generated Source Code

Generated assembly source code for words/data/code blocks is logically grouped into sections. Default order of sections is: init, boot, data, text.

Sections:

  • init - top of the output, typically contains user-provided assembly code block with org directive
  • boot - forth runtime
  • data - user data
  • text - core words and user program

User-defined data is output into the most recently declared data section (with [data-section] word), everything else is output into the most recently declared text section (with [text-section] word).

Syntax

Identifiers

Identifiers are case sensitive.

Constant and data identifiers consist of alphanumeric characters, '_'s, '-'s and '?'s and must start with a letter, '_', '-' or '?'. In generated assembly labels every '-' is replaced by '_' and every '?' is replaced by '_is_'.

Word identifiers consist of printable ASCII characters. Word identifiers consisting only of alphanumeric characters, '_'s, '-'s, '?'s and starting with a letter, '_', '-' or a '?' are translated automatically to valid assembly labels. Other word identifiers require user-defined label specification (see below).

Section identifiers consist of printable ASCII characters.

Comments

Syntax:


\ this is a one-line comment
( this is a multi-line
  comment)

Numbers

Syntax:


123   \ decimal number
$BA98 \ hexadecimal number

Word definitions

Syntax:

: name [ [label] asm-label ] words ;

or:

: name [ [label] asm-label ] [code]

; inline-assembly

[end-code] ;

Examples:


: foo begin end-flag until ;

: bar
[code]
 lda #1
 sta $D5E8
 jmp next
[end-code] ;

: +7 ( n1 -- n2 )
  [label] plus_7
  7 + ;

Data declarations

One-cell variable:

variable name

Two-cell variable:

2variable name

Assembly label at current program counter:

create name

Compile a one-cell value:

value ,

Compile a one-byte value:

value c,

Allocate a byte-array:

length allot

Allocate Atari XL/XE Antic counted string:

,' text'

Allocate ASCII counted string:

," text"

Allocate Atari XL/XE Antic string:

' text'

Allocate ASCII string:

" text"

Constants

Syntax:

value constant name

Example:


$230 constant dladr

Inline assembly blocks

Syntax:

[code]

; assembly code

[end-code]

Compiler directives

Syntax:

[text-section] name

or:

[data-section] name

Words

: @ 0= 1- 1+ 2/ 2* 2@ 2! and c! c@ cmove count d- d+ d= do drop dup fill i j loop +loop lshift <= < >= > - + or over rshift rsp sp swap unloop u< u> while <> >r r> = ! [ ] [code] [end-code] cell cells not [text-section] [data-section] variable 2variable constant create , c, ,' ' ," " allot lit \ ( recursive [label] * / m*

Usage

foco65 [OPTIONS] INPUT-FILE

OPTIONS:

-h                           display help
-p ADDR,--pstack-bottom=ADDR parameter stack bottom address
-s SECTS,--sections=SECTS    specify comma separated list of sections
                             default: init,boot,data,text
-S INT,--pstack-SIZE=INT     parameter stack size

Example:

$ foco65 foo.forth > foo.asx

Examples

Typical Atari XL/XE executable program structure.


[text-section] init

[code]
 org $2000
[end-code]

\ constant definitions
\ data declarations
\ word definitions

[text-section] text

: main
  \ user program initialization
  begin
    \ user program main loop
  again ;

[code]
 run boot
[end-code]

Atari XL/XE example: display character table.


[text-section] init

[code]
 org $3000
[end-code]

[text-section] text

$230 constant dladr

variable screen
variable cursor
variable line

: cursor-next   ( -- u )
  cursor @ dup 1+ cursor ! ;

: put-char      ( c -- )
  cursor-next c! ;

: set-cursor    ( u -- )
  screen @ + cursor ! ;
  
: main
  dladr @ 4 + @ screen !

  0 line !
  16 0 do
    line @ set-cursor
    line @ 40 + line !
    16 0 do
      i j 4 lshift or put-char
    loop
  loop

  begin again ;

[code]
 run boot
[end-code]

Atari XL/XE example of defining word in assembly: wait for keypress and push the pressed key's code on the parameter stack.


: get-char    ( -- c )
[code]
 lda #0
 dex
 sta pstack,x
 stx w
 jsr do_gc
 ldx w
 dex
 sta pstack,x
 jmp next

do_gc
 lda $E425
 pha
 lda $E424
 pha
 rts
[end-code] ;

Increase cell at the given address. Shows defining words not being a valid assembler label.


create array 16 cells allot

\ increase cell at given address
: ++          ( addr -- )
  [label] plus_plus
  dup @ 1+ swap ! ;