; ======================================================================
; SEDForth for Linux, Release 0.0.1
; Primitives (for inlining!)
; ======================================================================

code abs
 mov ebx,eax                ;set ebx = sign of n1
 sar ebx,31            ;propogate sign bit if n1 throughout ebx
 xor eax,ebx                ;will invert n1 if n1 was negative
 sub eax,ebx                ;will subtract -1 if n1 was negative
next

code minus
     sub [esi],eax			; -
     drop
next


code fmod
        upop ebx			; MOD
        xor edx,edx
        idiv ebx
        mov eax,edx
next

code plus
  add eax,[esi]			; +
  add esi,4
next

code divide
        upop ebx			; /
        xor edx,edx
        idiv ebx
next

code multiply
     mul dword [esi]			; *
     add esi, 4
next

code and
	and eax,[esi]
            add esi, 4
next

code equals
 sub eax,[esi]                ;subtract n1 from n2
 sub eax, 1             ;see if result was 0
 sbb eax,eax
 add esi, 4
next

code lessthan
 cmp eax,[esi]                ;compare them
 jl logic_less_1
 xor eax,eax                ;return result
 add esi,  4
next
logic_less_1:
 mov eax,dword -1           ;or this one :)
 add esi,  4
next

code max
 cmp eax, [esi]               ;which is larger
 jl logic_max_1              
 mov [esi], eax			;n2 is larger
logic_max_1:			;n1 is larger
 mov eax, [esi]
 add esi,  4
next

code min
 cmp eax, [esi]               ;which is smaller
 jg logic_min_1              
 mov [esi], eax			;n2 is smaller
logic_min_1:			;n1 is smaller
 mov eax, [esi]
 add esi,  4
next

code not
            not eax
next

code or
	      or eax,[esi]
            add esi, 4
next

code xor
	xor eax,[esi]
            add esi, 4
ret

base dd 10

code print
	push edx
	push edi
	mov edi,esi	;edi = buffer (in stack space)
	sub edi,4
	or eax,eax	;Negative?
	jns .a
	neg eax
	upsh '-'
	call forth_emit
.a:			;Convert
	xor edx,edx
	div dword [base]
	add dl,'0'
	cmp dl,'9'
	jbe .b
	add dl,7+32
.b:	dec edi
	mov [edi],dl
	or eax,eax
	jnz .a
	mov eax,edi	;Print
	upsh esi
	sub eax,edi	;# of digits
	call forth_type
	pop edi
	pop edx
	upsh ' '	; And add one space after
	call forth_emit	; the number
next

code type
	push ebx
	push ecx
	upop ecx
	upop ebx
	or ecx,ecx	; Is the count zero?
	jz .done	; If so, we can exit
	.a: push ecx	; store the count
	dup		; Duplicate it
	xor eax,eax 	; Filter out junk bits
	mov al,[ebx]	; Obtain the  to show
	inc ebx		; increment to the next 
	call forth_emit	; Show the character
	pop ecx		; Restore the count
	loop .a		; Loop, decrementing the count
.done:	pop ecx
	pop ebx
next


code cstore
	upop edx
	mov [edx], al
	drop
next
code cfetch
	upop edx
	dup
	xor eax,eax
	mov al, [edx]
next
code store
	upop edx
	mov [edx],eax
	drop
next
code callcomma
	mov ebx, eax
	drop
	call ebx
next
code spfetch
	upsh esi
next
code fetch
	mov eax,[eax]
next



s_dest dd 0
code s
	upop [s_dest]
	mov [tp],dword tib
.a:	call  forth_key
	cmp al,10
	je .done
	xchg edi,[tp]
	stosb
	xchg [tp],edi
	call forth_emit
	jmp  .a
.done:	push ecx	;move string to a safer place...
	push edi
	mov edi,[s_dest]
	mov eax,edi ;push addr
	dup
	push esi
	mov ecx,[tp]
	mov esi,tib
	sub ecx,esi
	mov eax,ecx	;push length
	rep movsb
	pop esi
	pop edi
	pop ecx
	call forth_cr
next

; ( source dest count -- )
code cmove
	mov ecx,eax
	drop
	mov edi,eax
	drop
	push esi
	mov esi,eax
.a:	mov edx, [esi] 
	mov [edi], edx
	inc edi
	inc esi
	loop .a
	pop esi
	drop
next



; =======================================================================
; Linux and Driver Specific Words
; =======================================================================
code bye
	sub ebx,ebx	;Return exit status 0
	mov eax,ebx
	inc eax		;1 = sys_exit
	int 80h
code cr
	upsh 10
	call forth_emit
	ret
code emit
	push edx
        push ecx
        push ebx
	mov ebx, 1	;stdout
	mov edx, ebx	;count
	lea ecx, [esp-4]
	mov [ecx], eax
	mov eax, 4	;sys_write
	int 80h
	pop ebx
        pop ecx
        pop edx
	drop
	ret
code key
	dup
;	push ebx,ecx,edx
	sub ebx,ebx	;0 = stdin
	mov edx, 1	;count
	lea ecx, [esp-4]
	mov eax, 3	;sys_read
	int 80h
	mov eax, [ecx]
;	pop ebx,ecx,edx
	ret
; =======================================================================
code dovar
	dup
	pop eax
	ret

h: call forth_dovar
dd h0
;---------------------------------------------------------------
; n SIZE x,

code xcomma
        upop ecx
	mov edx,[h]
	mov [edx],eax
	drop
	add edx,ecx
	mov [h],edx
	ret


tib rb 200h
h0 rb 80000h


tp dd tib
tin dd 0

code buffer
  upsh tib
ret
