;####################################################################
;#
;# Speicherstellen fuer den Daten-Stack
;#
;####################################################################

 !addr stl = $5000
 !addr sth = $5001

 !addr stp = $0334


;####################################################################
;#
;# Verwendete BASIC- und Kernal-Routinen
;#
;####################################################################

 !addr locate_var = $b0e7    ; Basic-Variable ermitteln
 !addr umult = $b357         ; 16-Bit-Werte multiplizieren
 !addr print_line_no = $bdcd ; 16-Bit-Wert ausgeben
 !addr chrout = $ffd2        ; Zeichen ausgeben


; -- aus dem 64er Assembler-Sonderheft Seite 51 --

udiv
 ldx #0
 stx $5c         ; Rest
 stx $5d
 ldy #16         ; Durchgaenge
-
 asl $57
 rol $58
 rol $5c
 rol $5d
 sec
 lda $5c         ; $5c/$5d - $59/$5a
 sbc $59
 tax
 lda $5d
 sbc $5a
 bcc +           ; Ergebnis < 0
 stx $5c
 sta $5d
 inc $57
+
 dey
 bne -
 rts


;####################################################################
;#
;# Makros
;#
;####################################################################

; Stackpointer initialisieren

 !macro initstp {
   ldx #0
 }


; Stackpointer erhoehen

 !macro incstp {
   inx
   inx
 }


; Stackpointer verringern

 !macro decstp {
   dex
   dex
 }


; Wert auf dem Stack ablegen (high byte muss im
; Hardware-Stack und low byte im A-Reg liegen)
; ( -- w ), [ b -- ]

 !macro push {
   sta stl,x
   pla
   sta sth,x
   +incstp
 }


; Festen Wert (literal) auf dem Stack ablegen
; ( -- w ), [ -- ]

 !macro lit .val {
   lda #>.val
   pha
   lda #<.val
   +push
 }


; Wert TRUE (1) auf dem Stack ablegen
; ( -- 1 ), [ -- ]

 !macro true {
   lda #0
   pha
   lda #1
   +push
 }


; Wert FALSE (0) auf dem Stack ablegen
; ( -- 0 ), [ -- ]

 !macro false {
   lda #0
   pha
   lda #0
   +push
 }


; Wert vom Stack holen (low byte liegt im A-Reg,
; und high byte auf dem Hardware-Stack)
; ( w -- ), [ -- b ]

 !macro pop {
   +decstp
   lda sth,x
   pha
   lda stl,x
 }

; Wert vom Stack entfernen
; ( w -- )

 !macro drop {
   +decstp
 }


; Wert aus einer Adresse auf dem Stack ablegen
; ( -- w ), [ -- ]

 !macro lod adr {
   lda adr+1
   pha
   lda adr
   +push
 }


; Wert vom Stack holen und an einer Adresse ablegen
; ( w -- ), [ -- ]

 !macro sto adr {
   +pop
   sta adr
   pla
   sta adr+1
 }


; Bedingter Sprung bei false
; ( 0|1 -- ), [ -- ]

 !macro jpc adr {
   +pop
   bne +
   pla
   bne ++
   jmp adr
+
   pla
++
 }


; Namen fuer Basic-Integervariable auf dem Stack ablegen
; ( -- v ), [ -- ]

 !macro litv .c1, .c2 {
   lda #.c1
   ora #$80
   pha
   lda #.c2
   ora #$80
   +push
 }


;####################################################################
;#
;# Funktionen
;#
;####################################################################

; ( w -- w w )

dup
 +decstp
 lda stl,x
 sta stl+2,x
 lda sth,x
 sta sth+2,x
 +incstp
 +incstp
 rts


; ( w1 w2 -- w2 w1 )

swap
 +decstp
 +decstp
 lda stl,x
 pha
 lda stl+2,x
 sta stl,x
 pla
 sta stl+2,x
 lda sth,x
 pha
 lda sth+2,x
 sta sth,x
 pla
 sta sth+2,x
 +incstp
 +incstp
 rts


; ( w1 w2 -- w1+w2 )

add
 +decstp
 +decstp
 clc
 lda stl,x
 adc stl+2,x
 sta stl,x
 lda sth,x
 adc sth+2,x
 sta sth,x
 +incstp
 rts


; ( w1 w2 -- w1-w2 )

sub
 +decstp
 +decstp
 sec
 lda stl,x
 sbc stl+2,x
 sta stl,x
 lda sth,x
 sbc sth+2,x
 sta sth,x
 +incstp
 rts


; ( w1 w2 -- w1*w2 )

mul
 +pop            ; zweiten Wert vom Stack holen und fuer umult ablegen
 sta $71
 pla
 sta $72
 +pop            ; ersten Wert vom Stack holen und fuer umult ablegen
 sta $28
 pla
 sta $29
 stx stp         ; Stackpointer sichern
 jsr umult
 tya             ; high byte steht in Y, low byte in X
 pha
 txa
 ldx stp         ; Stackpointer wieder laden
 +push           ; Ergebnis auf dem Stack ablegen
 rts


; ( w1 w2 -- w1/w2 w1%w2 )

divmod
 +pop            ; zweiten Wert vom Stack holen und fuer udiv ablegen
 sta $59
 pla
 sta $5a
 +pop            ; ersten Wert vom Stack holen und fuer udiv ablegen
 sta $57
 pla
 sta $58
 stx stp         ; Stackpointer sichern
 jsr udiv
 ldx stp         ; Stackpointer wieder laden
 lda $58         ; Ergebnis auf dem Stack ablegen
 pha
 lda $57
 +push
 lda $5d         ; Rest auf dem Stack ablegen
 pha
 lda $5c
 +push
 rts


; ( w1 w2 -- w1/w2)

div
 jsr divmod
 +drop
 rts


; ( w1 w2 -- w1%w2)

mod
 jsr divmod
 jsr swap
 +drop
 rts


; ( w -- w+1 )

incr
 +decstp
 inc stl,x
 bne +
 inc sth,x
+
 +incstp
 rts


; ( w w -- 0|1 ), [ -- ]

eql
 +decstp
 +decstp
 lda stl,x
 cmp stl+2,x
 bne +
 lda sth,x
 cmp sth+2,x
 bne +
 +true
 rts
+
 +false
 rts


; ( w w -- 0|1 ), [ -- ]

neq
 +decstp
 +decstp
 lda stl,x
 cmp stl+2,x
 bne +
 lda sth,x
 cmp sth+2,x
 bne +
 +false
 rts
+
 +true
 rts


; ( w w -- 0|1 )

lss
 jsr sub
 bcc +           ; Ergebnis < 0
 +drop
 +false
 rts
+
 +drop
 +true
 rts


; ( w w -- 0|1 )

geq
 jsr sub
 bcs +           ; Ergebnis >= 0
 +drop
 +false
 rts
+
 +drop
 +true
 rts


; Dezimalwert ausgeben
; ( w -- )

outdec
 +pop
 stx stp         ; Stackpointer sichern
 tax             ; low byte nach X
 pla             ; high byte nach A
 jsr print_line_no
 ldx stp         ; Stackpointer wieder laden
 rts


; Zeichen ausgeben (nur das low byte wird beachtet)
; ( w -- )

outchr
 +pop
 stx stp         ; Stackpointer sichern
 tax             ; low byte sichern
 pla             ; high byte verwerfen
 txa             ; low byte wieder holen
 jsr chrout
 ldx stp         ; Stackpointer wieder laden
 rts


; Wert einer Basic-Integervariablen laden (Variablen in
; Basic werden in der Reihenfolge high/low gespeichert)
; ( v -- w )

lodint
 +pop
 sta $46         ; zweites Zeichen des Namens (low byte)
 pla
 sta $45         ; erstes Zeichen des Namens (high byte)
 stx stp         ; Stackpointer sichern
 jsr locate_var
 ldx stp         ; Stackpointer wieder laden
 ldy #0          ; high byte des Variablenwertes laden
 lda ($47),y
 pha
 iny             ; low byte des Variablenwertes laden
 lda ($47),y
 +push
 rts


; Wert in einer Basic-Integervariablen speichern (Variablen in
; Basic werden in der Reihenfolge high/low gespeichert)
; ( w v -- )

stoint
 +pop
 sta $46         ; zweites Zeichen des Namens (low byte)
 pla
 sta $45         ; erstes Zeichen des Namens (high byte)
 stx stp         ; Stackpointer sichern
 jsr locate_var
 ldx stp         ; Stackpointer wieder laden
 +pop
 ldy #1          ; low byte des Werts speichern
 sta ($47),y
 dey             ; high byte des Werts speichern
 pla
 sta ($47),y
 rts