	[const sp $5d][const sph $5e]
	[const sreg $5f]
	  [const c 0][const z 1]

	[const pinb $23][const ddrb $24][const portb $25]
	  [const run-led 5][const bootmode 4]
	[const ddrd $2a][const portd $2b]

	[const udr0 $c6][const ubrr0h $c5][const ubrr0l $c4]
	[const ucsr0c $c2][const ucsr0b $c1]
	[const ucsr0a $c0]
	  [const rxc0 7][const udre0  5]
	[const tccr0a $44][const tccr0b $45][const tcnt0 $46][const ocr0a $47]
	[const timsk0 $6e][const tifr0 $35]
	[const tccr1a $80][const tccr1b $81][const ocr1al $88][const ocr1ah $85]
	[const tifr1 $36][const timsk1 $6f]

	[const eearl $41][const eearh $42][const eedr $40]
	[const eecr $3f]
	  [const eere 0][const eepe 1][const eempe 2]


	[const bootsp $100][const bootsph $101]	; some bytes in this region 
	[const monsp $102][const monsph $103]	; get clobbered by reset
	[const endsp $104][const endsph $105]
	[const seed $106][const seedh $107]
	[const ticks $108][const ticksh $109]
	[const timer-t0 $10a][const timer-t0h $10b]

	[const powerup-flag $200][const idle $201]
	[const secph $202][const secphh $203]
	[const seconds $204][const secondsh $205]
	[const minuteph $206]	
	[const minutes $207][const minutesh $208]
	[const globals $210]



	[const cc $8000]		; start of eeprom
	[const pin-init-addr $83f0]		
	[const powerup-addr $83f4]	
	[const startup-addr $83f8]	
	[const cmd-vector $83fc]	


;---------------
;
; monitor
;

start	[jmp init]
	[jmp $3f00][jmp $3f00][jmp $3f00]	;2
	[jmp $3f00][jmp $3f00][jmp $3f00][jmp $3f00]	;5
	[jmp $3f00][jmp $3f00][jmp $3f00][jmp $3f00] ;9
	[jmp $3f00][jmp $3f00][jmp tmr0_oca][jmp $3f00]	;13
	[jmp $3f00][jmp $3f00][jmp $3f00][jmp $3f00]	;17
	[jmp $3f00][jmp $3f00][jmp $3f00][jmp $3f00]	;21
	[jmp $3f00][jmp $3f00]	;25

init	[lds d0 sp][sts d0 bootsp]
	[lds d0 sph][sts d0 bootsph]
	[rcall hardware-init]
	[sei]
	[ldi z 0][ldi zh $08][lpm]
	[mov d0 t0][cpi d0 $ff][breq loop]				; test for code ok
	[sbis pinb bootmode][rjmp loop]			; emergency escape to monitor
	[ldi z [byte0 :pin-init-addr]]
	[ldi zh [byte1 :pin-init-addr]]
	[andi zh $7f][rcall ee-readfb]
	[mov d0 t0][cpi d0 $0a][brne loop]		; check for a valid pin-init vector
	[ldi ip [byte0 :pin-init-addr]]
	[ldi iph [byte1 :pin-init-addr]]
	[rcall start-eval]
	[lds d0 powerup-flag][cpi d0 $5a][breq in50]
	[ldi d0 0]
	[sts d0 secph][sts d0 secphh][sts d0 minuteph]
	[sts d0 seconds][sts d0 secondsh]
	[sts d0 minutes][sts d0 minutesh]
	[ldi ip [byte0 :powerup-addr]]
	[ldi iph [byte1 :powerup-addr]]
	[rcall start-eval]
	[ldi d0 $5a][sts d0 powerup-flag]
	[rjmp loop]
in50	[lds d0 idle][cpi d0 $a5][brne loop]	
	[ldi d1 0][sts d1 idle]
	[ldi ip [byte0 :startup-addr]]
	[ldi iph [byte1 :startup-addr]]
	[rcall start-eval]

loop	[ldi d0 $a5][sts d0 idle]
	[rcall getc]
	[ldi d1 0][sts d1 idle]
	[inc d0][breq i'm-here]
	[inc d0][breq read-data-byte]
	[inc d0][breq write-data-bytes]
	[inc d0][breq read-flash-word]
	[inc d0][breq return-to-bootloader]
	[inc d0][breq run-vm]
	[inc d0][breq read-ee-byte]
	[inc d0][breq .write-ee-byte]
	[inc d0][breq run-cmd]
	[rjmp loop]

.write-ee-byte [rjmp write-ee-byte]

i'm-here
	[ldi d0 $23][rcall putc]
	[rjmp loop]

return-to-bootloader
	[ldi d0 0][sts d0 tccr1a]		; optiboot is finicky about tmr1
	[lds d0 bootsp][sts d0 sp]
	[lds d0 bootsph][sts d0 sph]
	[cli]
	[ret]

run-cmd	[rcall run-cmd-vector]
	[ldi d0 $7f][rcall putc]
	[rjmp loop]

run-vm	[rcall run-cc]
	[ldi d0 $af][rcall putc]
	[rjmp loop]


read-data-byte
	[rcall getc][mov x d0]
	[rcall getc][mov xh d0]
	[ld@x d0]
	[rcall putc]
	[rjmp loop]

write-data-bytes
	[rcall getc][mov x d0]
	[rcall getc][mov xh d0]
	[rcall getc][mov t0 d0]
wdb20	[rcall getc][st@x+ d0]
	[dec t0][brne wdb20]
	[rjmp loop]

read-flash-word
	[rcall getc][mov z d0]
	[rcall getc][mov zh d0]
	[add z z][adc zh zh]
	[lpm][mov d0 r0][rcall putc]
	[inc z][lpm][mov d0 r0][rcall putc]
	[rjmp loop]

read-ee-byte
	[rcall getc][sts d0 eearl]
	[rcall getc][sts d0 eearh]
	[sbi eecr eere]
	[lds d0 eedr]
	[rcall putc]
	[rjmp loop]

write-ee-byte
	[rcall getc][sts d0 eearl]
	[rcall getc][sts d0 eearh]
	[rcall getc][sts d0 eedr]
	[sbi eecr eempe][sbi eecr eepe]
web20	[sbic eecr eepe][rjmp web20]
	[ldi d0 $8f][rcall putc]
	[rjmp loop]

getc	[lds d1 ucsr0a]
	[sbrs d1 rxc0][rjmp getc]
	[lds d0 udr0]
	[ret]

putc	[lds d1 ucsr0a]
	[sbrs d1 udre0][rjmp putc]
	[sts d0 udr0]
	[ret]
	

hardware-init
	[ldi d0 16][sts d0 ubrr0l]
	[eor d0 d0][sts d0 ubrr0h]
	[ldi d0 2][sts d0 ucsr0a]		; u2x
	[ldi d0 $18][sts d0 ucsr0b]		; rxen, txen
	[ldi d0 6][sts d0 ucsr0c]		; 8N1
	[ldi d0 2][out d0 tccr0a]		; ctc mode
	[ldi d0 3][out d0 tccr0b]		; / 64
	[ldi d0 250][out d0 ocr0a]
	[ldi d0 2][sts d0 timsk0]	; oca int
	[sbi ddrb run-led]
	[cbi portb run-led]
	[sbi portb bootmode]		; pullup on for the bootmode pin
	[ret]

;---------------
;
; vm
;

run-cmd-vector
	[ldi ip [byte0 :cmd-vector]]
	[ldi iph [byte1 :cmd-vector]]
	[rjmp start-eval]

run-cc	[ldi ip [byte0 :cc]]
	[ldi iph [byte1 :cc]]

start-eval
	[sbi portb run-led]
	[lds d0 sp][sts d0 monsp]
	[lds d0 sph][sts d0 monsph]
	[lds d0 ticks][ori d0 1][sts d0 seed]
	[lds d0 ticksh][ori d0 1][sts d0 seedh]

poll	[lds d1 ucsr0a]
	[sbrc d1 rxc0][rjmp eval-done]
eval	[rcall fetch]
	[ldi z [byte0 :eval-table]]
	[ldi zh [byte1 :eval-table]]
	[ldi d0 0][add z t0][adc zh d0]
	[ijmp]

eval-table
	[rjmp eval-done]
	[rjmp eval-byte][rjmp eval-num]
	[rjmp eval-list][rjmp eval-eol][rjmp eval-eolr]
	[rjmp eval-lthing][rjmp eval-lmake]
	[rjmp eval-gthing][rjmp eval-gmake]
	[rjmp eval-ufun]
	[rjmp prim-stop][rjmp prim-output]
	[rjmp prim-loop][rjmp prim-repeat]
	[rjmp prim-if][rjmp prim-ifelse]
	[rjmp prim-waituntil]
	[rjmp prim-sum][rjmp prim-diff]
	[rjmp prim-mul][rjmp prim-div]
	[rjmp prim-rem]
	[rjmp prim-gr][rjmp prim-lt]
	[rjmp prim-eq][rjmp prim-neq]
	[rjmp prim-and][rjmp prim-or]
	[rjmp prim-xor][rjmp prim-not]
	[rjmp prim-byte1][rjmp prim-byte0]
	[rjmp prim-leftshift]
	[rjmp prim-random]
	[rjmp prim-readfb]
	[rjmp prim-readb][rjmp prim-writeb]
	[rjmp prim-bsetb][rjmp prim-bclrb][rjmp prim-btstb] 
	[rjmp prim-read][rjmp prim-write]
	[rjmp prim-bset][rjmp prim-bclr] 
	[rjmp prim-wait][rjmp prim-mwait]
	[rjmp prim-resett][rjmp prim-timer][rjmp prim-ticks]
	[rjmp prim-resets][rjmp prim-seconds]
	[rjmp prim-resetm][rjmp prim-minutes]
	[rjmp prim-print][rjmp prim-prh][rjmp prim-prhb]
	[rjmp prim-prs][rjmp prim-prf]
	[rjmp prim-ufdiv][rjmp prim-ufmul]

eval-done
	[lds d0 sp][sts d0 endsp]
	[lds d0 sph][sts d0 endsph]
	[lds d0 monsp][sts d0 sp]
	[lds d0 monsph][sts d0 sph]
	[cbi portb run-led]
	[ret]

eval-byte
	[rcall fetch]
	[ldi d0 0]
	[push d0][push t0]
	[rjmp eval]

eval-num
	[rcall fetch][mov d0 t0]
	[rcall fetch]
	[push t0][push d0]
	[rjmp eval]

eval-list
	[rcall fetch][mov d0 t0]
	[rcall fetch]
	[push iph][push ip]
	[add ip d0][adc iph t0]
	[rjmp eval]

eval-eolr
	[pop d0][pop d1]
	[pop zh][pop z]
	[push d1][push d0]
	[ijmp]

eval-eol
	[ret]

get-local-address
	[rcall fetch]
	[ldi d0 0]
	[sbrc t0 7][ldi d0 $ff]
	[movw y fp]
	[sbrs t0 7][adiw y 7]
	[sbrc t0 7][adiw y 1]
	[add y t0][adc yh d0]
	[add y t0][adc yh d0]
	[ret]

eval-lthing
	[rcall get-local-address]
	[ld@y+ d0][ld@y+ d1]
	[push d1][push d0]
        [rjmp eval]

eval-lmake
	[rcall get-local-address]
	[pop d0][pop d1]
	[st@y+ d0][st@y+ d1]
	[rjmp poll]

eval-gthing
	[rcall fetch]
	[add t0 t0][sub t1 t1]
	[ldi x [byte0 :globals]]
	[ldi xh [byte1 :globals]]
	[add x t0][adc xh t1]
	[ld@x+ d0][ld@x d1]
	[push d1][push d0]
	[rjmp eval]

eval-gmake
	[pop d0][pop d1]
	[rcall fetch]
	[add t0 t0][sub t1 t1]
	[ldi x [byte0 :globals]]
	[ldi xh [byte1 :globals]]
	[add x t0][adc xh t1]
	[st@x+ d0][st@x d1]
	[rjmp eval]

eval-ufun
	[rcall fetch][mov x t0]
	[rcall fetch][mov xh t0]
	[push iph][push ip]
	[movw ip x]
	[rcall fetch]
	[eor t1 t1][push t1][push t0]
	[rcall fetch]		; fetch locals (ignored for now)
	[push fph][push fp]
	[lds fp sp][lds fph sph]
	[or t0 t0][breq eu90]
eu20	[push t0][push t0]
	[dec t0][brne eu20]
eu90	[rjmp eval]


prim-stop
	[sts fp sp][sts fph sph]
	[pop fp][pop fph]
	[pop t0][pop t1]
	[pop ip][pop iph]
	[lds t2 sp][lds t3 sph]
	[add t0 t0][adc t1 t1]
	[add t0 t2][adc t1 t3]
	[sts t0 sp][sts t1 sph]
	[rjmp poll]

prim-output
	[pop d0][pop d1]
	[sts fp sp][sts fph sph]
	[pop fp][pop fph]
	[pop t0][pop t1]
	[pop ip][pop iph]
	[lds t2 sp][lds t3 sph]
	[add t0 t0][adc t1 t1]
	[add t0 t2][adc t1 t3]
	[sts t0 sp][sts t1 sph]
	[push d1][push d0]
	[rjmp poll]

prim-loop
	[pop ip][pop iph]
	[push iph][push ip]
	[ldi d0 [byte0 :prim-loop]][push d0]
	[ldi d0 [byte1 :prim-loop]][push d0]
	[rjmp eval]
	
prim-repeat
	[push iph][push ip]
rep20	[lds y sp][lds yh sph]
	[ldd@y x 5][ldd@y xh 6]
	[mov d0 x][or d0 xh][breq rep80]
	[sbiw x 1]
	[std@y x 5][std@y xh 6]
	[ldd@y ip 3][ldd@y iph 4]
	[ldi d0 [byte0 :rep20]][push d0]
	[ldi d0 [byte1 :rep20]][push d0]
	[rjmp eval]
rep80	[pop ip][pop iph]
	[pop d0][pop d0]
	[pop d0][pop d0]
	[rjmp poll]


prim-ifelse
	[pop d0][pop d1]
	[pop d2][pop d3]
	[pop t0][pop t1]
	[or t0 t1][breq run-r0]
	[movw d0 d2]
	[rjmp run-r0]

prim-if	[pop d0][pop d1]
	[pop d2][pop d3]
	[or d3 d2][breq if90]
run-r0	[push iph][push ip]
	[movw ip d0]
        [ldi d1 [byte1 :if80]]
        [ldi d0 [byte0 :if80]]
	[push d0][push d1]
	[rjmp eval]
if80	[pop ip][pop iph]
if90	[rjmp poll]

prim-waituntil
	[push iph][push ip]
wun20	[ldi d0 [byte0 :wun80]][push d0]
	[ldi d0 [byte1 :wun80]][push d0]
	[lds y sp][lds yh sph]
        [ldd@y ip 5][ldd@y iph 6]
        [rjmp poll]
wun80   [pop d0][pop d1]
        [or d0 d1][breq wun20]
        [pop ip][pop iph]
        [pop d0][pop d0]
        [rjmp poll]

prim-sum
	[pop d0][pop d1]
	[pop d2][pop d3]
	[add d0 d2][adc d1 d3]
	[push d1][push d0]
	[rjmp eval]

prim-diff
	[pop d2][pop d3]
	[pop d0][pop d1]
	[sub d0 d2][sbc d1 d3]
	[push d1][push d0]
	[rjmp eval]

prim-mul
        [rcall pop-signed-nums]
	[mul d2 d4][movw d0 t0]
	[mul d2 d5][add d1 t0]
	[mul d3 d4][add d1 t0]
	[brtc mul50]
	[eor t0 t0][eor t1 t1]
	[sub t0 d0][sbc t1 d1]
	[movw d0 t0]
mul50	[push d1][push d0]
	[rjmp eval]

prim-div
	[rcall pop-signed-nums]
	[rcall unsigned-divide]
	[brtc div50]
	[eor t0 t0][eor t1 t1]
	[sub t0 d0][sbc t1 d1]
	[movw d0 t0]
div50	[push d1][push d0]
	[rjmp eval]
	
prim-rem
	[rcall pop-signed-nums]
	[rcall unsigned-divide]
	[mov t0 d2][or t0 d3][breq rem80]
	[cpi yh 0][brmi negmod]
	[cpi xh 0][brpl rem80]
	[sub y d2][sbc yh d3][movw d2 y]
	[rjmp rem80]
negmod	[cpi xh 0][brmi rem50]
	[add d2 y][adc d3 yh]
	[rjmp rem80]
rem50	[eor t0 t0][eor t1 t1]
	[sub t0 d2][sbc t1 d3]
	[movw d2 t0]
rem80	[push d3][push d2]
	[rjmp eval]

unsigned-divide
        [eor d0 d0][eor d1 d1]           ; clear the result register
        [mov t0 d4][or t0 d5]
        [breq div90]     		 ; don't divide by zero
        [eor d7 d7][ldi d6 1] 		 ; set the addend to 1
div20   [rcall cmp-nums]
        [brcc div40]
        [add d6 d6][adc d7 d7]
        [add d4 d4][adc d5 d5]
        [brcc div20]
div40	[lsr d7][ror d6]
        [lsr d5][ror d4]
        [mov t0 d6][or t0 d7]
        [breq div90]
        [rcall cmp-nums]
        [brcc div40]
	[sub d2 d4][sbc d3 d5]
	[add d0 d6][adc d1 d7]
        [rjmp div40]
div90	[ret]

cmp-nums[cp d5 d3]             ; compare the high bytes
        [brne cpn90]            ; if neq then return right away
        [cp d4 d2]             ; otherwise check the low bytes
	[brne cpn90]
	[sec]
cpn90   [ret]

pop-signed-nums
	[pop zh][pop z]
	[pop d4][pop d5]
	[movw y d4]		; save the signed second arg
	[pop d2][pop d3]
	[movw x d2]		; save the signed first arg
	[mov t0 d5][eor t0 d3]
	[bst t0 7]
	[sbrs d5 7][rjmp psn50]
	[eor t0 t0][eor t1 t1]
	[sub t0 d4][sbc t1 d5]
	[movw d4 t0]
psn50	[sbrs d3 7][rjmp psn90]
	[eor t0 t0][eor t1 t1]
	[sub t0 d2][sbc t1 d3]
	[movw d2 t0]
psn90	[ijmp]


prim-ufdiv
        [eor d0 d0][eor d1 d1]  ; clear the result register
	[pop t6][pop t7]	;divisor
	[eor t5 t5][eor t4 t4]
	[pop t2][pop t3]	; dividend
	[eor t1 t1][eor t0 t0]
        [eor d3 d3][eor d2 d2]  ; init the addend
	[sec]
ufdiv40	[ror d3][ror d2]
        [lsr t7][ror t6][ror t5][ror t4]
        [mov t8 d3][or t8 d2]
        [breq ufdiv90]
        [rcall cmp-nums32]
        [brcc ufdiv40]
	[sub t0 t4][sbc t1 t5]
	[sbc t2 t6][sbc t3 t7]
	[add d0 d2][adc d1 d3]
	[clc][rjmp ufdiv40]
ufdiv90	[push d1][push d0]
	[rjmp eval]

cmp-nums32
	[cp t7 t3][brne cpn32-90] 
        [cp t6 t2][brne cpn32-90]
        [cp t5 t1][brne cpn32-90]
        [cp t4 t0][brne cpn32-90]
	[sec]
cpn32-90 
	[ret]

prim-ufmul
	[eor t3 t3]
	[pop d2][pop d3]	; arg2
	[pop d0][pop d1]	; arg1
	[mul d0 d2][movw t4 t0]
	[mul d1 d3][movw t6 t0]
	[mul d1 d2][add t5 t0][adc t6 t1][adc t7 t3]
	[mul d0 d3][add t5 t0][adc t6 t1][adc t7 t3]
	[push t7][push t6]
	[rjmp eval]
	
prim-gr	[pop d2][pop d3]
	[pop d0][pop d1]
	[mov t0 d1][eor t0 d3]
	[sbrc t0 7][rjmp gr80]	
	[sub d0 d2][sbc d1 d3]
	[mov t0 d0][or t0 d1][breq return-false]
gr80	[sbrs d1 7][rjmp return-true]
	[rjmp return-false]

prim-lt	[pop d2][pop d3]
	[pop d0][pop d1]
	[mov t0 d1][eor t0 d3]
	[sbrc t0 7][rjmp lt80]	
	[sub d0 d2][sbc d1 d3]
lt80	[sbrs d1 7][rjmp return-false]
	[rjmp return-true]

prim-eq	[pop d2][pop d3]
	[pop d0][pop d1]
	[cp d0 d2][brne return-false]
	[cp d1 d3][brne return-false]
return-true
	[eor d0 d0][push d0]
	[ldi d0 1][push d0]
	[rjmp eval]
	
prim-neq
	[pop d2][pop d3]
	[pop d0][pop d1]
	[cp d0 d2][brne return-true]
	[cp d1 d3][brne return-true]
return-false
	[eor d0 d0]
	[push d0][push d0]
	[rjmp eval]

prim-and
	[pop d0][pop d1]
	[pop d2][pop d3]
	[and d0 d2][and d1 d3]
	[push d1][push d0]
	[rjmp eval]

prim-or
	[pop d0][pop d1]
	[pop d2][pop d3]
	[or d0 d2][or d1 d3]
	[push d1][push d0]
	[rjmp eval]

prim-xor
	[pop d0][pop d1]
	[pop d2][pop d3]
	[eor d0 d2][eor d1 d3]
	[push d1][push d0]
	[rjmp eval]

prim-not
	[pop d0][pop d1]
	[or d0 d1][breq not90]
	[rjmp return-false]
not90	[rjmp return-true]

prim-byte1
	[pop d0][pop d1]
	[eor d2 d2]
	[push d2][push d1]
	[rjmp eval]

prim-byte0
	[pop d0][pop d1]
	[eor d2 d2]
	[push d2][push d0]
	[rjmp eval]

prim-leftshift
	[pop d2][pop d3]
	[pop d0][pop d1]
	[or d2 d2][breq lsh90][brmi rightshift]
lsh20	[add d0 d0][adc d1 d1]
	[dec d2][brne lsh20]
lsh90	[push d1][push d0]
	[rjmp eval]

rightshift
	[neg d2]
rsh20	[lsr d1][ror d0]
	[dec d2][brne rsh20]
	[push d1][push d0]
	[rjmp eval]

prim-random
	[pop d4][pop d5]
	[lds d0 seed][lds d1 seedh]
	[ldi d2 17]
ran20	[eor d3 d3]
	[sbrc d1 7][inc d3]
	[sbrc d0 4][inc d3]
	[sbrc d0 2][inc d3]
	[sbrc d0 1][inc d3]
	[add d0 d0][adc d1 d1]
	[andi d3 1][add d0 d3]
	[dec d2][brne ran20]
	[sts d0 seed][sts d1 seedh]
	[andi d1 $7f]
	[movw d2 d0]
	[rcall unsigned-divide]
	[push d3][push d2]
	[rjmp eval]

prim-readfb
	[pop z][pop zh]
	[call readfb][eor d0 d0]
	[push d0][push t0]
	[rjmp eval]

prim-readb
	[pop x][pop xh]
	[ld@x d0][eor d1 d1]
	[push d1][push d0]
	[rjmp eval]

prim-writeb
	[pop d0][pop d1]
	[pop x][pop xh]
	[st@x d0]
	[rjmp poll]

prim-bsetb
	[pop d0][pop d1]
	[pop x][pop xh]
	[ld@x d2][or d2 d0][st@x d2]
	[rjmp poll]

prim-bclrb
	[pop d0][pop d1]
	[pop x][pop xh]
	[ldi d2 $ff][eor d0 d2]
	[ld@x d2][and d2 d0][st@x d2]
	[rjmp poll]

prim-btstb
	[pop d0][pop d1]
	[pop x][pop xh]
	[ld@x d2][and d2 d0]
	[breq btstb80]
	[rjmp return-true]
btstb80	[rjmp return-false]


prim-read
	[pop x][pop xh]
	[ld@x+ d0][ld@x d1]
	[push d1][push d0]
	[rjmp eval]

prim-write
	[pop d0][pop d1]
	[pop x][pop xh]
	[st@x+ d0][st@x d1]
	[rjmp poll]

prim-bset
	[pop d0][pop d1]
	[pop x][pop xh]
	[ld@x d2][or d2 d0][st@x+ d2]
	[ld@x d2][or d2 d1][st@x d2]
	[rjmp poll]

prim-bclr
	[pop d0][pop d1]
	[pop x][pop xh]
	[ldi d2 $ff][eor d0 d2][eor d1 d2]
	[ld@x d2][and d2 d0][st@x+ d2]
	[ld@x d2][and d2 d1][st@x d2]
	[rjmp poll]

prim-resett
	[cli][lds d0 ticks][lds d1 ticksh][sei]
	[sts d0 timer-t0][sts d1 timer-t0h]
	[rjmp poll]
	
prim-timer
	[cli][lds d0 ticks][lds d1 ticksh][sei]
	[lds d2 timer-t0][lds d3 timer-t0h]
	[sub d0 d2][sbc d1 d3]
	[andi d1 $7f]
	[push d1][push d0]
	[rjmp eval]

prim-resets
	[ldi d0 0]
	[sts d0 seconds][sts d0 secondsh]
	[rjmp poll]
	
prim-seconds
	[cli][lds d0 seconds][lds d1 secondsh][sei]
	[push d1][push d0]
	[rjmp eval]

prim-resetm
	[ldi d0 0]
	[sts d0 minutes][sts d0 minutesh]
	[rjmp poll]
	
prim-minutes
	[cli][lds d0 minutes][lds d1 minutesh][sei]
	[push d1][push d0]
	[rjmp eval]

prim-ticks
	[cli][lds d0 ticks][lds d1 ticksh][sei]
	[push d1][push d0]
	[rjmp eval]

prim-wait
	[ldi x 100][ldi xh 0]
	[pop y][pop yh]
	[rcall milli-wait]
	[sbiw y 1][push yh][push y]
	[brne prim-wait]
	[pop t0][pop t0]
	[rjmp poll]

prim-mwait
	[pop x][pop xh]
	[rcall milli-wait]
	[rjmp poll]

milli-wait
mw20	[lds d1 ucsr0a]
	[sbrc d1 rxc0][rjmp mw90]
	[lds t0 ticks]
mw50	[lds t1 ucsr0a][sbrc t1 rxc0][ret]
mw70	[lds t1 ticks]
	[cp t0 t1][breq mw50]
	[sbiw x 1][brne mw20]
mw90	[ret]

prim-prf
	[pop d2][pop d3]
	[pop z][pop zh]
prf20	[rcall readfb][mov d0 t0][adiw z 1]
	[cpi d0 0][breq prf90]
	[cpi d0 37][brne prf50]
	[rcall prf-escape]
	[rjmp prf20]
prf50	[rcall putc]
	[rjmp prf20]
prf90	[rjmp poll]

prf-escape
	[rcall readfb][mov d0 t0][adiw z 1]
	[cpi d0 98][breq prfhb]		; %b
	[cpi d0 119][breq prfh]		; %w
	[cpi d0 100][breq prfd]		; %d
	[rjmp putc]
prfhb	[rjmp prhb]
prfh	[rjmp prh]
prfd	[mov t0 d2][mov t1 d3]
	[rjmp prd]
	
prim-prs
	[pop z][pop zh]
prs20	[rcall readfb][mov d0 t0][adiw z 1]
	[or d0 d0][breq prs90]
	[rcall putc]
	[rjmp prs20]
prs90	[ldi d0 13][rcall putc]
	[rjmp poll]

prim-print
	[pop t0][pop t1]
	[rcall prd]
	[ldi d0 13][rcall putc]
	[rjmp poll]


prd	[sbrs t1 7][rjmp pp20]
	[movw t2 t0]
	[eor t0 t0][eor t1 t1]
	[sub t0 t2][sbc t1 t3]
	[ldi d0 [ascii "-]][rcall putc]
pp20	[clt]
        [ldi d0 [byte0 10000]]
        [ldi d1 [byte1 10000]]
        [rcall do-digit]
        [ldi d0 [byte0 1000]]
        [ldi d1 [byte1 1000]]
        [rcall do-digit]
        [ldi d0 [byte0 100]]
        [ldi d1 [byte1 100]]
        [rcall do-digit]
        [ldi d0 [byte0 10]]
        [ldi d1 [byte1 10]]
        [rcall do-digit]
        [ldi d0 48]     ;convert to ascii
	[add d0 t0]
	[rjmp putc]

do-digit
        [eor t2 t2]
dd20    [sub t0 d0][sbc t1 d1]
        [inc t2]
        [sbrs t1 7] [rjmp dd20]
        [add t0 d0][adc t1 d1]
        [dec t2][brne dd60]
        [brts dd60]
        [ret]                   ; got a leading zero so don't print
dd60    [set]
        [ldi d0 48]     ;convert to ascii
	[add d0 t2]
	[rjmp putc]

prim-prh
	[pop d2][pop d3]
	[rcall prh]
	[ldi d0 13][rcall putc]
	[rjmp poll]

prim-prhb
	[pop d2][pop d3]
	[rcall prhb]
	[ldi d0 13][rcall putc]
	[rjmp poll]

prh	[push d2][mov d2 d3]
	[rcall prhb]
	[pop d2]
prhb	[mov d0 d2]
	[lsr d0][lsr d0]
	[lsr d0][lsr d0]
	[rcall prh-digit]
	[mov d0 d2][andi d0 $0f]
prh-digit
	[ldi d1 7]
	[cpi d0 10][in t0 sreg]
	[sbrs t0 c][add d0 d1]
	[ldi d1 $30][add d0 d1]
	[rjmp putc]

fetch	[movw z ip][adiw ip 1]
readfb	[sbrc zh 7][rjmp ee-readfb]
	[lpm]
	[ret]
	
ee-readfb
	[sts z eearl]
	[sts zh eearh]
	[sbi eecr eere]
	[lds t0 eedr]
	[ret]

tmr0_oca
	[push x][push xh]
	[in x sreg][push x]
	[lds x ticks][lds xh ticksh]
	[adiw x 1]
	[sts x ticks][sts xh ticksh]
	[lds x secph][lds xh secphh]
	[adiw x 1]
	[sts x secph][sts xh secphh]
	[cpi x [byte0 1000]][brne tmr80]
	[cpi xh [byte1 1000]][brne tmr80]
	[ldi x 0][sts x secph][sts x secphh]
	[lds x seconds][lds xh secondsh]
	[adiw x 1][andi xh $7f]
	[sts x seconds][sts xh secondsh]
	[lds x minuteph][inc x][sts x minuteph]
	[cpi x 60][brne tmr80]
	[ldi x 0][sts x minuteph]
	[lds x minutes][lds xh minutesh]
	[adiw x 1][andi xh $7f]
	[sts x minutes][sts xh minutesh]
tmr80	[pop x][out x sreg]
	[pop xh][pop x]
	[reti]

end
