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

; Eigene Ideen
; Datenstack - ein zweiter Stack, emuliert, und dennoch IRQ-sicher :-)

; pushdasr/popdasr bewahrt die Flags
popdasr         macro   dst        ; Holt etwas vom Datenstack
                  mov.attribute     @r4+, dst ; Lese Adresse in r4 aus und erhöhe danach r4 um 2.
                endm

pushdasr        macro   src        ; Legt etwas auf den Datenstack
                  push sr              ; Notwendig, damit die Flags nicht verändert werden
                  decd r4              ; Stackpointer aktualisieren
                  pop sr               ; so kann ich auch sr auf den Datenstack legen.
                  mov.attribute src, @r4 ; und Wert an Ort und Stelle bringen.
                endm    

; pushda/popda kümmert sich neuerdings nicht mehr um die Flags... 
; Änderung am 21. September 2007 und Auslagerung in eine neue Datei, damit die alten Programme nicht plötzlich seltsame Fehler zeigen ;-)

popda           macro   dst        ; Holt etwas vom Datenstack - 2 Bytes
                  mov     @r4+, dst ; Lese Adresse in r4 aus und erhöhe danach r4 um 2.
                endm

;popdabyte       macro dst
;                  mov.b @r4, dst
;                  incd r4
;                endm

; Achtung: popda.b erhöht den Stackzeiger nur um 1... Vorsicht also !

pushda          macro   src        ; Legt etwas auf den Datenstack - 4 Bytes
                  decd r4              ; Stackpointer aktualisieren
                  mov src, @r4 ; und Wert an Ort und Stelle bringen.
                endm
; Achtung: popdabyte hat noch ein Problem: Der High-Teil wird nicht geleert,
;          sondern behält seinen letzten zufälligen Wert.
;pushdabyte      macro   src        ; Legt etwas auf den Datenstack - 4 Bytes
;                  decd r4              ; Stackpointer aktualisieren
;                  mov.b src, @r4 ; und Wert an Ort und Stelle bringen.
;                endm
    
; Der Datenstack ist nicht für Bytezugriffe geeignet, das macht viel zu viele Probleme !
; Aussortiert am 24. Februar 2010 nach einer langen, mysteriösen Fehlersuche

; Fehlen tut noch: swap, over, rot, 2swap, 2dup, 2over, 2drop
; SWAP ( n1 n2 -- n2 n1 ) Reverses the top two stack items.
; DUP ( n -- n n ) Duplicates the top stack item.
; OVER ( n1 n2 -- n1 n2 n1 ) Makes a copy of the second item and pushes it on top.
; ROT ( n1 n2 n3 -- n2 n3 n1 ) Rotates the third item to the top.
; DROP ( n -- ) Discards the top stack item.

dup             macro
                  pushda 2(r4)
                endm  

over            macro
                  pushda 4(r4)
                endm
                
swap            macro
                  push 2(r4)         ; ( B A ) R : B
                  mov @r4,   2(r4)   ; ( A A ) R : B
                  pop @r4            ; ( A B ) R : B
                endm  
       
  ifdef 0                
swap            macro ; Genauso lang, Alternative.
                  push @r4           ; ( B A ) R : A
                  mov 2(r4), @r4     ; ( B B ) R : A
                  pop 2(r4)          ; ( A B ) R : A
                endm  
  endif              
                                
; rot ( 1 2 3 -- 2 3 1 ) Rotiert das dritte Element an die Spitze.
rot             macro                ; ( 1 2 3 )
                  push @r4           ; ( 1 2 3 ) R: 3
                  mov 4(r4), 0(r4)   ; ( 1 2 1 ) R: 3
                  mov 2(r4), 4(r4)   ; ( 2 2 1 ) R: 3
                  pop 2(r4)          ; ( 2 3 1 ) R: 3
                endm

; rot rot rot ist die Identität.

; Verwirft das oberste Element des Datenstacks
drop            macro ; 2 Bytes lang
                  incd r4
                endm
                
nip macro
      ; NIP ( x1 x2 -- x2 ) Drop the first item below the top of stack. 
      mov @r4+, 0(r4) ; Löscht das zweite Element aus dem Stack.
    endm                
                
; Die zweite Hand - der Return-Stack... Hin und her !                
to_r            macro ; >R  2 Bytes lang
                  push @r4+
                endm  
  
r_from          macro ; R>  4 Bytes lang
                  pushda @sp+
                endm

; Schnelle Rechenoperationen

plus		macro
                  add @r4+, 0(r4)  ; Die beiden oberen Elemente des Datenstacks addieren
                endm

minus           macro                
                  sub @r4+, 0(r4)
                endm  

negate macro ; Kehrt das Vorzeichen um
         inv @r4
         inc @r4
       endm

abs macro ; Berechnet den Absolutwert einer Zahl
      tst @r4
      jn +
      jmp ++
+     negate
+
    endm                