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

; Enthält Routinen, die einen Einblick in das Innenleben ermöglichen.

;------------------------------------------------------------------------------
  Kapitelbirne_flash "--- Einblicke ---"  
;------------------------------------------------------------------------------ 

;------------------------------------------------------------------------------  
; Einige interne Helferlein.
;------------------------------------------------------------------------------  
  ifdef 0 ; Zahlenausgabe, wenn es weder dot noch udot gibt. Braucht nur wenig Platz !
;------------------------------------------------------------------------------
schreibenibble: ; ( Datennibble -- )
                ; Schreibt vier Bits als Hexadezimalziffer über die serielle Leitung hinaus
;------------------------------------------------------------------------------
  push r10
 
  popda r10 ; Nibble holen
  and #0Fh, r10 ; Nur die untersten 4 Bits beachten

  ; 0 bis 9: 
  cmp #10, r10
  jhs +
  add #48, r10 ; Ab ASCII 48 beginnen die Zahlen
  jmp ++

+ ; 10 bis 15
  add #55, r10 ; Ab ASCII 65 beginnen die Großbuchstaben
+ pushda r10
  call #emit

  pop r10
  ret

;------------------------------------------------------------------------------
schreibebyte: ; ( Datenbyte -- )
              ; Schreibt ein Byte hexadezimal über die serielle Leitung hinaus
;------------------------------------------------------------------------------
  push r10
  mov @r4, r10 
  rra r10
  rra r10
  rra r10
  rra r10
  pushda r10
 
  call #schreibenibble ; High-Nibble
  call #schreibenibble ; Low-Nibble
  pop r10
  ret

;------------------------------------------------------------------------------
schreibeword: ; (Datenword -- )
              ; Schreibt ein Word hexadezimal über die serielle Leitung hinaus
;------------------------------------------------------------------------------
  dup
  swpb @r4
  call #schreibebyte
  call #schreibebyte
  ret

  endif

  ifdef 0
;------------------------------------------------------------------------------  
schreibeboolean: ; ( -- ) Gibt das Carry-Flag aus
;------------------------------------------------------------------------------  
  push sr
  jnc +
  write " true "
  pop sr
  ret
+ write " false "
  pop sr
  ret  

writeboolean macro
  call #schreibeboolean
  endm  

  endif

;------------------------------------------------------------------------------  
; Makros, um diese Routinen komfortabel benutzen zu können
;------------------------------------------------------------------------------  
  ifdef 0
writezahl macro Zahl
  pushda Zahl
  call #schreibeword
  endm  
  
writebyte macro Zahl
  decd r4
  clr @r4
  mov.b Zahl, @r4
  call #schreibebyte
  endm   
  endif

writezahl macro Zahl
  pushda Zahl
  call #udot
  endm  
  
writebyte macro Zahl
  decd r4
  clr @r4
  mov.b Zahl, @r4
  call #udot
  endm    

;------------------------------------------------------------------------------
  Wortbirne Flag_sichtbar, "words"
;  Wortbirne Flag_sichtbar, "wortliste"
wortliste: ; ( -- ) Gibt die Wörterliste aus
;------------------------------------------------------------------------------ 
  push r10
  push &Base
  mov #16, &Base

  ifdef flashdictionaryeinbinden
  cmp #nBacklinkgrenze, &DictionaryPointer ; tst &WritetoFlash
  jhs +                                   ; jnz +
  ; Fürs Ram:
    mov &Fadenende, r10
    jmp ++
+ ; Für den Flash
    mov #CoreDictionaryAnfang, r10
+
  else ; Wenn es nur das gewöhnliche Ram-Dictionary gibt
    mov &Fadenende, r10
  endif
  
  ; ( Fadenstück -- )

  ; r10 enthält die Adresse, an der die Liste beginnen soll.
  writeln ""

- ; Aufbau: Flags     Namenslänge
  ;         Name...   0
  ;         Link (zum Nachbarwort - nach vorn oder nach hinten ist egal)
  ;         Code

  ifdef flashdictionaryeinbinden
  ; Ist an der Stelle der Flags und der Namenslänge $FFFF ? Dann ist der Faden abgelaufen.
  cmp #0FFFFh, @r10
  je +
  endif

  ; Habe einen Dictionaryeintrag gefunden !
  write "Address: "
  writezahl r10
  write " Flags: "
  writebyte @r10
  inc r10
  ;pushda r10 ; Adresse für die Namensausgabe
 
  ;pushda r10
  pushdadouble r10, r10
  call #stringueberlesen
  mov @r4, r10 ; Platz auf Datenstack freilassen

  ; Angekommen im Linkfeld.
  write " Link: "
  mov @r10, @r4
  call #udot
 
  ; Schreibe noch die Codestartadresse.
  write " Code: "
  pushda r10
  incd @r4
  call #udot
    
  ; Codestartadresse ist mir einfach mal egal. Das war einmal.
  write " Name: "
  call #schreibestringmitlaenge
  
  writeln "";writeln " >"  

  cmp #0FFFFh, @r10  ; -1 markiert Ende
  je +

  ; Folge dem Link
  mov @r10, r10
  jmp -

+ pop &Base
  pop r10
  ret

;------------------------------------------------------------------------------
  Wortbirne Flag_sichtbar, ".s"
dotS: ; Zeichnet den Datenstack, benutzt für mich unsigned-Zahlen.
      ; Besonders nützlich für Logik, Adressen und Zähler.
;------------------------------------------------------------------------------ 

  push r10
  push r11
  mov #datenstackanfang, r10  ; Obere Adresse vom Stack.
  mov r10, r11                ; Duplikat anlegen
  sub r4, r11                 ; Datenstackpointer von der oberen Adresse abziehen ergibt Füllstand.
    
  write " Stack: ["

dotseinsprung:
  clrc
  rrc r11                     ; Füllstand durch 2 Teilen, da Stack Words aufnimmt.

  ; Habe nun den Pointer in r10, die Zahl der zu schreibenden Words in r11.  
  
  push &Base      ; Füllstand schreiben
  mov #10, &Base  
    writezahl r11
  pop &Base
  
  write "] "
  
  tst r11 ; Schon Null, Datenstack leer ?
  je +

- decd r10      ; Inhalt ausgeben:
  writezahl @r10
  
  dec r11
  jz +
  write ", "
  jmp -
      
+ writeln " *>"
  
  pop r11
  pop r10
  ret
 
;------------------------------------------------------------------------------
  Wortbirne Flag_sichtbar, ".rs"
dotRS: ; Zeichnet den Returnstack, benutzt für mich unsigned-Zahlen.
      ; Besonders nützlich für Logik, Adressen und Zähler.            130 Bytes
;------------------------------------------------------------------------------ 
  push r10
  push r11
  mov #returnstackanfang, r10 ; Obere Adresse vom Stack.
  mov r10, r11                ; Duplikat anlegen
  sub sp, r11                 ; Stackpointer von der oberen Adresse abziehen ergibt Füllstand + 6.
  sub #6, r11                 ; Einsprung von .rs und die beiden gesicherten Register überspringen
    
  write " Returnstack: ["
  jmp dotseinsprung
 

;------------------------------------------------------------------------------
  Kapitelbirne "--- Einblicke ---"  
;------------------------------------------------------------------------------ 