;
;    Mecrisp - A native code Forth implementation for MSP430 microcontrollers
;    Copyright (C) 2011  Matthias Koch
;
;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;    (at your option) any later version.
;
;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.
;
;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.
;

; Forth for MSP430 architecture.

; Early beginnings on 20. Juny 2009.
; Started development on 18. February 2010 and finished main ideas of Mecrisp roughly in August 2011.
; But development goes on...

; 16 Bit Implementation, between subroutine threading and native code generation with constant folding and opcoding.
; Supports Unicode (utf8).

; No register optimisations, TOS in stack.
; Register with exception of SR are saved before use !
; Watch for interrupts and care to reserve space on stacks BEFORE putting values into.
; Because of that there are no unsaved, temporary registers, altough they could help to save code space.

; Register allocation:

; r0    PC
; r1    SP
; r2    SR
; r3    CG

; r4    Pointer for data stack
; r5    Index for loops
; r6    Limit for loops
; r7    Scratch register which is only saved on interrupt entry.
; r8  free
; r9  free

; r10    Heavy use ! Working registers that are saved every time.
; r11    ''
; r12    ''
; r13    ''
; r14    ''
; r15    ''

; Dictionary-Construction:
;  ---------------------------------
;  1 Byte Flags (immediate, inline and some others),
;  1 Byte Length of name
;  ---------------------------------
;  Name. If it is an uneven count of characters,
;        it is padded with one zero for alignment that is not counted in length byte.
;  ---------------------------------
;  Link. 2 Bytes. Points to flags of next definition.
;  ---------------------------------
;  After that, machine code begins. Everytime available, everytime executable.
;  Code + ret -- or a call/jump that never returns.
;  ---------------------------------
;  Optional: Data field. There is no link into. 
;            If you need it, search for ret opcode.

; Flag meaning: (hex)
;
;   FF  Invisible (Unsichtbar)
;
;   00  Visible (Sichtbar)
;   10  Immediate
;   20  Inline
;   30  Immediate&Inline at once: Immediate, Compile-Only
;   40  Foldable / Opcodable (Faltbar / Opcodierbar)
;   80  Allocates Ram (automatically 0-foldable)
;
;   More close:
;
;     Foldable/Opcodable:
;     40  0-Foldable
;     41  1-Foldable
;     .   ...
;     47  7-Foldable
;
;     "48" is base for opcodable cases:
;     49  Opcodable Calculus&Logic (Opcodierbar Rechenlogik) automatically 2-foldable (often in combination with inline: 69)
;     4A  Opcodable Write Memory   (Opcodierbar Speicherschreiben)
;     4B  Opcodable  Read Memory   (Opcodierbar Speicherlesen)
;     4C  Opcodable Special Case   (Opcodierbar Spezialfall)
;

; Definitions for Flags in Dictionary

Flag_invisible  equ 0FFh ; Not set = Not written to in flash
Flag_visible    equ  0b
Flag_immediate  equ  10000b
Flag_inline     equ 100000b

Flag_visible_immediate equ Flag_visible|Flag_immediate
Flag_visible_inline    equ Flag_visible|Flag_inline

; Immediate and Inline cannot coexist. Because of that I use this combination for immediate, compile-only.
Flag_immediate_compileonly equ Flag_visible|Flag_immediate|Flag_inline 

Flag_foldable     equ 1000000b ; To check for Foldability
Flag_opcodierbar equ    1000b  ; To check for Opcodability

Flag_foldable_0 equ Flag_foldable|0
Flag_foldable_1 equ Flag_foldable|1
Flag_foldable_2 equ Flag_foldable|2
Flag_foldable_3 equ Flag_foldable|3
Flag_foldable_4 equ Flag_foldable|4
Flag_foldable_5 equ Flag_foldable|5
Flag_foldable_6 equ Flag_foldable|6
Flag_foldable_7 equ Flag_foldable|7

; Of course, some of those cases are not foldable at all. But this way their bitmask is constructed.
Flag_opcodierbar_rechenlogik       equ Flag_foldable|Flag_opcodierbar|1
Flag_opcodierbar_speicherschreiben equ Flag_foldable|Flag_opcodierbar|2
Flag_opcodierbar_speicherlesen     equ Flag_foldable|Flag_opcodierbar|3
Flag_opcodierbar_spezialfall       equ Flag_foldable|Flag_opcodierbar|4

  ifdef ramverwaltungeinbinden
Flag_ramallot equ 10000000b
Flag_variable equ Flag_ramallot|1
  endif

;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Beginning of Dictionary !
; Start with header definitions.

  ifndef flashdictionaryeinbinden

; Normal case for standard links, it there is ram dictionary only

Latest set 0FFFFh ; Pointer to last defined word
Neu    set 0FFFFh ; Variable for current pointer

Wortbirne macro Flagzustand, Name
  align 2
Neu set $ ; Save current address for link
  .byte Flagzustand, STRLEN(Name), Name
  align 2
  .word Latest
Latest set Neu
          endm

  else ; flashdictionaryeinbinden

    ifdef ramverwaltungeinbinden
CoreVariablenPointer set nRamDictionaryEnde

CoreVariable macro Name ; Use this mechanism to get initialised variables.
CoreVariablenPointer set CoreVariablenPointer - 2
Name equ CoreVariablenPointer
             endm
    endif ; ramverwaltungeinbinden


; Basically, this macro gives every definition its own label and defines it in the following definition.
; 1. Usage: .word Backlink_1
; 2. Usage: Backlink_1 gets defined and .word Backlink_2 is included
; Follow up. At the end, the last Backlink has to be defined manually.

Backlink_Zaehler set 0
Backlink_Label   set "\{Backlink_Zaehler}"

Wortbirne macro Flagzustand, Name
  align 2

Backlink_{Backlink_Label} equ $ ; Save current address for former Backlink.

Backlink_Zaehler set Backlink_Zaehler+1 ; Select next Label
Backlink_Label   set "\{Backlink_Zaehler}"  ; and assemble it.

  .byte Flagzustand, STRLEN(Name), Name
  align 2
  .word Backlink_{Backlink_Label} ; Include special links here.

          endm

; At the end:
; Backlink_{Backlink_Label} equ nFlashDictionaryAnfang ; Set pointer into changeable dictionary space.

  endif ; flashdictionaryeinbinden

;------------------------------------------------------------------------------
CoreDictionaryAnfang: ; Contains whole dictionary
;------------------------------------------------------------------------------

  include "terminal.asm"
  include "stackjugglers.asm"
  include "logic.asm"

  ifdef doppeltzahleneinbinden
    ifdef fixkommarechnungeneinbinden
      include "fixpoint.asm"
    endif
    include "double.asm"
  endif

  include "starslash.asm"
  include "strings.asm"
  include "calculations.asm"
  include "memory.asm"

  ifdef flashdictionaryeinbinden
    include "flash.asm"
  endif

  include "query.asm"
  include "deepinsight.asm"
  include "numberstrings.asm"
  include "interpreter.asm"
  include "compiler.asm"
  include "controlstructures.asm"

  ifdef caseeinbinden
    include "case.asm"
  endif

  include "comparisions.asm"

  ifdef analogeinbinden
    include "analog.asm"
  endif

  ; Take care: Those parts have a lot of dependencies !

  ifdef interrupthookseinbinden
    include "interrupts.asm"
  endif

  ifdef taktlauschereinbinden
    include "ledcomm.asm"
  endif

;------------------------------------------------------------------------------

  ifdef flashdictionaryeinbinden
; Set latest link into user changeable flash dictionary.
Backlink_{Backlink_Label} equ nFlashDictionaryAnfang ; Dies ist der Zeiger in das veränderliche Flash-Dictionary.

  else ; For Ram-only:

CoreFadenende equ Latest
CoreDictionaryEnde equ $

  endif
