mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			2842 lines
		
	
	
		
			51 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
			
		
		
	
	
			2842 lines
		
	
	
		
			51 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
;; A Forth by Chris Hinsley
 | 
						|
;; nasm -f macho forth.nasm
 | 
						|
;; ld -o forth -e _main forth.o
 | 
						|
;; ./forth
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	%define VERSION_NUM 30
 | 
						|
 | 
						|
	; various buffer area sizes
 | 
						|
	%define DATA_STACK_SIZE 1024
 | 
						|
	%define USER_DEFS_SIZE (64*1024)
 | 
						|
	%define NUM_HASH_CHAINS 64
 | 
						|
	%define MAX_LINE_SIZE 128
 | 
						|
 | 
						|
	%define SYS_exit 1
 | 
						|
	%define SYS_read 3
 | 
						|
	%define SYS_write 4
 | 
						|
	%define SYS_open 5
 | 
						|
	%define SYS_close 6
 | 
						|
	%define SYS_unlink 10
 | 
						|
	%define	SYS_mprotect 74
 | 
						|
	%define SYS_fsync 95
 | 
						|
	%define SYS_rename 128
 | 
						|
	%define SYS_stat 188
 | 
						|
	%define SYS_lseek 199
 | 
						|
	%define SYS_fstat 189
 | 
						|
	%define SYS_ftruncate 201
 | 
						|
 | 
						|
	%define PROT_READ 0x01		;pages can be read
 | 
						|
	%define PROT_WRITE 0x02		;pages can be written
 | 
						|
	%define PROT_EXEC 0x04		;pages can be executed
 | 
						|
	%define PROT_ALL (PROT_READ | PROT_WRITE | PROT_EXEC)
 | 
						|
	%define PAGE_SIZE 4096
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; some NASM codeing macros
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	%macro loopstart 0
 | 
						|
		%push loopstart
 | 
						|
	%$loop_start:
 | 
						|
	%endmacro
 | 
						|
 | 
						|
	%macro break 0
 | 
						|
		jmp %$loop_exit
 | 
						|
	%endmacro
 | 
						|
 | 
						|
	%macro breakif 1
 | 
						|
		j%+1 %$loop_exit
 | 
						|
	%endmacro
 | 
						|
 | 
						|
	%macro loopend 0
 | 
						|
		jmp %$loop_start
 | 
						|
	%$loop_exit:
 | 
						|
		%pop
 | 
						|
	%endmacro
 | 
						|
 | 
						|
	%macro repeat 0
 | 
						|
		%push repeat
 | 
						|
	%$loop_start:
 | 
						|
	%endmacro
 | 
						|
 | 
						|
	%macro until 1
 | 
						|
		j%-1 %$loop_start
 | 
						|
	%$loop_exit:
 | 
						|
		%pop
 | 
						|
	%endmacro
 | 
						|
 | 
						|
	%macro if 1
 | 
						|
		%push if
 | 
						|
		j%-1 %$ifnot
 | 
						|
	%endmacro
 | 
						|
 | 
						|
	%macro else 0
 | 
						|
		%ifctx if
 | 
						|
			%repl else
 | 
						|
			jmp %$ifend
 | 
						|
		%$ifnot:
 | 
						|
		%else
 | 
						|
			%error "expected `if' before `else'"
 | 
						|
		%endif
 | 
						|
	%endmacro
 | 
						|
 | 
						|
	%macro endif 0
 | 
						|
		%ifctx if
 | 
						|
		%$ifnot:
 | 
						|
			%pop
 | 
						|
		%elifctx else
 | 
						|
		%$ifend:
 | 
						|
			%pop
 | 
						|
		%else
 | 
						|
			%error "expected `if' or `else' before `endif'"
 | 
						|
		%endif
 | 
						|
	%endmacro
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;
 | 
						|
; base VM macros
 | 
						|
;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	; eip	Forths IP
 | 
						|
	; esp	Forths R
 | 
						|
	; ebp	Forths S
 | 
						|
	; ebx	Forths TOS
 | 
						|
 | 
						|
	; push on to return stack
 | 
						|
	%macro PUSHRSP 1
 | 
						|
		push %1
 | 
						|
	%endm
 | 
						|
 | 
						|
	; pop top of return stack
 | 
						|
	%macro POPRSP 1
 | 
						|
		pop %1
 | 
						|
	%endm
 | 
						|
 | 
						|
	; save into return stack
 | 
						|
	%macro PUTRSP 2
 | 
						|
		%if (%2 = 0)
 | 
						|
			mov [esp], %1
 | 
						|
		%elif ((%2 >= -128) && (%2 < 128))
 | 
						|
			mov [byte esp + %2], %1
 | 
						|
		%else
 | 
						|
			mov [long esp + %2], %1
 | 
						|
		%endif
 | 
						|
	%endm
 | 
						|
 | 
						|
	; load from return stack
 | 
						|
	%macro PICKRSP 2
 | 
						|
		%if (%2 = 0)
 | 
						|
			mov %1, [esp]
 | 
						|
		%elif ((%2 >= -128) && (%2 < 128))
 | 
						|
			mov %1, [byte esp + %2]
 | 
						|
		%else
 | 
						|
			mov %1, [long esp + %2]
 | 
						|
		%endif
 | 
						|
	%endm
 | 
						|
 | 
						|
	; set return stack
 | 
						|
	%macro SETRSP 1
 | 
						|
		mov esp, %1
 | 
						|
	%endm
 | 
						|
 | 
						|
	; get return stack
 | 
						|
	%macro GETRSP 1
 | 
						|
		mov %1, esp
 | 
						|
	%endm
 | 
						|
 | 
						|
	; adjust return stack
 | 
						|
	%macro ADDRSP 1
 | 
						|
		%if ((%1 >= -128) && (%1 < 128))
 | 
						|
			add esp, byte %1
 | 
						|
		%else
 | 
						|
			add esp, %1
 | 
						|
		%endif
 | 
						|
	%endm
 | 
						|
 | 
						|
	; push on to data stack
 | 
						|
	%macro PUSHDSP 1
 | 
						|
		sub ebp, byte 4
 | 
						|
		mov [ebp], %1
 | 
						|
	%endm
 | 
						|
 | 
						|
	; pop top of data stack
 | 
						|
	%macro POPDSP 1
 | 
						|
		mov %1, [ebp]
 | 
						|
		add ebp, byte 4
 | 
						|
	%endm
 | 
						|
 | 
						|
	; save into data stack
 | 
						|
	%macro PUTDSP 2
 | 
						|
		%if (%2 = 0)
 | 
						|
			mov [ebp], %1
 | 
						|
		%elif ((%2 >= -128) && (%2 < 128))
 | 
						|
			mov [byte ebp + %2], %1
 | 
						|
		%else
 | 
						|
			mov [long ebp + %2], %1
 | 
						|
		%endif
 | 
						|
	%endm
 | 
						|
 | 
						|
	; load from data stack
 | 
						|
	%macro PICKDSP 2
 | 
						|
		%if (%2 = 0)
 | 
						|
			mov %1, [ebp]
 | 
						|
		%elif ((%2 >= -128) && (%2 < 128))
 | 
						|
			mov %1, [byte ebp + %2]
 | 
						|
		%else
 | 
						|
			mov %1, [long ebp + %2]
 | 
						|
		%endif
 | 
						|
	%endm
 | 
						|
 | 
						|
	; set data stack
 | 
						|
	%macro SETDSP 1
 | 
						|
		mov ebp, %1
 | 
						|
	%endm
 | 
						|
 | 
						|
	; get data stack
 | 
						|
	%macro GETDSP 1
 | 
						|
		mov %1, ebp
 | 
						|
	%endm
 | 
						|
 | 
						|
	; adjust data stack
 | 
						|
	%macro ADDDSP 1
 | 
						|
		%if ((%1 >= -128) && (%1 < 128))
 | 
						|
			add ebp, byte %1
 | 
						|
		%else
 | 
						|
			add ebp, %1
 | 
						|
		%endif
 | 
						|
	%endm
 | 
						|
 | 
						|
	; load value onto data stack
 | 
						|
	%macro LOADTOS 1
 | 
						|
		PUSHDSP ebx
 | 
						|
		mov ebx, %1
 | 
						|
	%endm
 | 
						|
 | 
						|
	; move from data to return stack
 | 
						|
	%macro TORSP 0
 | 
						|
		PUSHRSP ebx
 | 
						|
		POPDSP ebx
 | 
						|
	%endm
 | 
						|
 | 
						|
	; move from return to data stack
 | 
						|
	%macro FROMRSP 0
 | 
						|
		PUSHDSP ebx
 | 
						|
		POPRSP ebx
 | 
						|
	%endm
 | 
						|
 | 
						|
	; copy from return to data stack
 | 
						|
	%macro FETCHRSP 0
 | 
						|
		PUSHDSP ebx
 | 
						|
		PICKRSP ebx, 0
 | 
						|
	%endm
 | 
						|
 | 
						|
	; align reg
 | 
						|
	%define DP_ALIGN 3
 | 
						|
	%macro ALIGNREG 1
 | 
						|
		add %1, byte DP_ALIGN
 | 
						|
		and %1, byte ~DP_ALIGN
 | 
						|
	%endm
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; dictionary building macros
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	; format of dictionary entry flag byte
 | 
						|
	%define F_IMMED 0x80
 | 
						|
	%define F_HIDDEN 0x20
 | 
						|
	%define F_LENMASK 0x1f
 | 
						|
 | 
						|
	%define NULL 0
 | 
						|
	%define H_LLINK 0
 | 
						|
	%define H_HLINK 4
 | 
						|
	%define H_NSIZE 8
 | 
						|
	%define H_NAME 9
 | 
						|
 | 
						|
	%define XT_BODY -12
 | 
						|
	%define XT_LENGTH -8
 | 
						|
	%define XT_COMPILE -4
 | 
						|
	%define XT_SIZE 12
 | 
						|
	
 | 
						|
	%macro defword 4
 | 
						|
		%push newword
 | 
						|
		%strlen len %1
 | 
						|
		align 4
 | 
						|
	dic_%3:
 | 
						|
		dd NULL				; LATEST list link
 | 
						|
		dd NULL				; hash chain link
 | 
						|
		db len + %2			; flags + length byte
 | 
						|
		db %1				; the name
 | 
						|
		dd %3				; body pointer
 | 
						|
		dd %$code_end - %3	; code length
 | 
						|
		dd %4				; compile action word
 | 
						|
	%3:
 | 
						|
	%endm					; assembler code follows
 | 
						|
 | 
						|
	%macro defword_end 0
 | 
						|
	%$code_end:
 | 
						|
		%pop
 | 
						|
	%endm
 | 
						|
 | 
						|
	%macro defvar 4
 | 
						|
		defword %1, %2, %3, WORD_INLINE_COMMA
 | 
						|
		LOADTOS var_%3
 | 
						|
		ret
 | 
						|
		defword_end
 | 
						|
		align 4
 | 
						|
	var_%3:
 | 
						|
		dd %4
 | 
						|
	%endm
 | 
						|
 | 
						|
	%macro defvar2 5
 | 
						|
		defword %1, %2, %3, WORD_INLINE_COMMA
 | 
						|
		LOADTOS var_%3
 | 
						|
		ret
 | 
						|
		defword_end
 | 
						|
		align 4
 | 
						|
	var_%3:
 | 
						|
		dd %4
 | 
						|
		dd %5
 | 
						|
	%endm
 | 
						|
 | 
						|
	%macro defconst 4
 | 
						|
		defword %1, %2, %3, WORD_INLINE_COMMA
 | 
						|
		LOADTOS %4
 | 
						|
		ret
 | 
						|
		defword_end
 | 
						|
	%endm
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; entry point
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	SECTION .text
 | 
						|
	global _main
 | 
						|
_main:
 | 
						|
	; use mprotect to allow read/write/execute of the data section
 | 
						|
	mov edx, forth_start
 | 
						|
	and edx, -PAGE_SIZE		;start address
 | 
						|
	mov ecx, forth_end
 | 
						|
	sub ecx, edx			;length
 | 
						|
	mov ebx, PROT_ALL		;flags
 | 
						|
	push ebx
 | 
						|
	push ecx
 | 
						|
	push edx
 | 
						|
	push 0					;padding
 | 
						|
	mov eax, SYS_mprotect
 | 
						|
	int 0x80
 | 
						|
	add esp, 16
 | 
						|
	jmp forth_start
 | 
						|
 | 
						|
	SECTION .data
 | 
						|
forth_start:
 | 
						|
	; init data and return stacks, saving initial positions
 | 
						|
	; in Forth vars R0 and S0
 | 
						|
	cld
 | 
						|
	GETRSP [var_WORD_SZ]
 | 
						|
	SETDSP [var_WORD_SZ]
 | 
						|
	ADDRSP -DATA_STACK_SIZE
 | 
						|
	GETRSP [var_WORD_RZ]
 | 
						|
 | 
						|
	; link built in dictionary
 | 
						|
	mov esi, dictionary_start
 | 
						|
	xor edi, edi
 | 
						|
	repeat
 | 
						|
		lodsd
 | 
						|
		mov [eax + H_LLINK], edi
 | 
						|
		mov edi, eax
 | 
						|
		push esi
 | 
						|
		mov cl, [eax + H_NSIZE]
 | 
						|
		and ecx, F_LENMASK
 | 
						|
		lea esi, [eax + H_NAME]
 | 
						|
		call strhashi
 | 
						|
		and ebx, NUM_HASH_CHAINS-1
 | 
						|
		mov esi, hash_buckets
 | 
						|
		mov eax, [esi + (ebx * 4)]
 | 
						|
		mov [esi + (ebx * 4)], edi
 | 
						|
		mov [edi + H_HLINK], eax
 | 
						|
		pop esi
 | 
						|
		cmp esi, dictionary_end
 | 
						|
	until z
 | 
						|
	mov [var_WORD_LATEST], edi
 | 
						|
 | 
						|
	; run temp interpreter loop till we can get into the real QUIT word
 | 
						|
	call WORD_LBRAC			; interpret state
 | 
						|
	LOADTOS 666q			; octal !
 | 
						|
	TORSP
 | 
						|
	LOADTOS 0
 | 
						|
	TORSP
 | 
						|
	LOADTOS bootfile
 | 
						|
	TORSP
 | 
						|
	call WORD_SYS_OPEN
 | 
						|
	call WORD_SYSCALL
 | 
						|
	ADDRSP 12
 | 
						|
	TORSP					; ( fd ) of "forth.f"
 | 
						|
	loopstart
 | 
						|
		LOADTOS tib_buffer
 | 
						|
		LOADTOS MAX_LINE_SIZE
 | 
						|
		FETCHRSP			; ( c-addr len fd )
 | 
						|
		call WORD_READLINE	; ( num flag flag )
 | 
						|
		call WORD_DROP2
 | 
						|
		LOADTOS tib_buffer
 | 
						|
		call WORD_SWAP
 | 
						|
		call WORD_INHASH
 | 
						|
		call WORD_STORE2
 | 
						|
		LOADTOS 0
 | 
						|
		call WORD_TOIN
 | 
						|
		call WORD_STORE
 | 
						|
		call WORD_INTERPRET
 | 
						|
	loopend					; and loop till QUIT takes over
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; a few case insensative string operations
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	%macro to_lower 1
 | 
						|
		; lower case check
 | 
						|
		cmp %1, 'A'
 | 
						|
		if ge
 | 
						|
			cmp %1, 'Z'
 | 
						|
			if le
 | 
						|
				; make it lower case
 | 
						|
				add %1, byte 'a' - 'A'
 | 
						|
			endif
 | 
						|
		endif
 | 
						|
	%endm
 | 
						|
 | 
						|
strcpyi:
 | 
						|
	test ecx, ecx
 | 
						|
	if nz
 | 
						|
	strcpyi_l1:
 | 
						|
		lodsb
 | 
						|
		to_lower al
 | 
						|
		stosb
 | 
						|
		loop strcpyi_l1
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
 | 
						|
strcmpi:
 | 
						|
	test ecx, ecx
 | 
						|
	if nz
 | 
						|
	strcmpi_l1:
 | 
						|
		lodsb
 | 
						|
		mov bl, [edi]
 | 
						|
		lea edi, [edi + 1]
 | 
						|
		to_lower al
 | 
						|
		to_lower bl
 | 
						|
		cmp bl, al
 | 
						|
		if z
 | 
						|
			loop strcmpi_l1
 | 
						|
		endif
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;
 | 
						|
; hash function
 | 
						|
;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
strhashi:
 | 
						|
	mov ebx, 5381
 | 
						|
	test ecx, ecx
 | 
						|
	if nz
 | 
						|
		mov edx, 33
 | 
						|
	strhashi_l1:
 | 
						|
		lodsb
 | 
						|
		movzx eax, al
 | 
						|
		to_lower eax
 | 
						|
		imul ebx, edx
 | 
						|
		add ebx, eax
 | 
						|
		loop strhashi_l1
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;
 | 
						|
; syscall functions
 | 
						|
;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
_syscall:
 | 
						|
	int 0x80
 | 
						|
	if c
 | 
						|
		neg eax
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
 | 
						|
_lsyscall:
 | 
						|
	int 0x80
 | 
						|
	if c
 | 
						|
		not eax
 | 
						|
		not edx
 | 
						|
		add eax, 1
 | 
						|
		adc edx, 0
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; built in variables
 | 
						|
; STATE		Is the interpreter executing code (0) or compiling a word (non-zero)?
 | 
						|
; LATEST	Points to the latest (most recently defined) word in the dictionary.
 | 
						|
; DP		Points to the next free byte of memory. When compiling, compiled words go here.
 | 
						|
; S0		Stores the address of the top of the parameter stack.
 | 
						|
; R0		The address of the top of the return stack.
 | 
						|
; BASE		The current base for printing and reading numbers.
 | 
						|
; #IN		The current input buffer descriptor.
 | 
						|
; >IN		The current input offset.
 | 
						|
; SOURCEFD	The current input source file descriptor.
 | 
						|
; BLK		The current block number.
 | 
						|
; CHARBUF	Single char buffer.
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defvar "state", 0, WORD_STATE, 0
 | 
						|
	defvar "dp", 0, WORD_DP, dictionary_start
 | 
						|
	defvar "latest", 0, WORD_LATEST, 0
 | 
						|
	defvar "s0", 0, WORD_SZ, 0
 | 
						|
	defvar "r0", 0, WORD_RZ, 0
 | 
						|
	defvar "base", 0, WORD_BASE, 10
 | 
						|
	defvar2 "#IN", 0, WORD_INHASH, 0, 0
 | 
						|
	defvar ">in", 0, WORD_TOIN, 0
 | 
						|
	defvar "sourcefd", 0, WORD_SOURCEFD, 0
 | 
						|
	defvar "blk", 0, WORD_BLK, 0
 | 
						|
	defvar "charbuf", 0, WORD_CHARBUF, 0
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; built in constants
 | 
						|
; VERSION		The current version of this FORTH.
 | 
						|
; WORDBUF		The address of the buffer WORD uses.
 | 
						|
; LINESIZE		The line buffer size.
 | 
						|
; F_IMMED		The IMMEDIATE flag's actual value.
 | 
						|
; F_HIDDEN		The HIDDEN flag's actual value.
 | 
						|
; F_LENMASK		The length mask in the flags/len byte.
 | 
						|
; H_NSIZE		The flags/len field offset.
 | 
						|
; H_NAME		The name field offset.
 | 
						|
; XT_BODY		The xt body pointer.
 | 
						|
; XT_LENGTH		The xt length field offset.
 | 
						|
; XT_COMPILE	The xt compile field offset.
 | 
						|
; XT_SIZE		The xt size offset.
 | 
						|
; SYS_*			The numeric codes of various syscalls.
 | 
						|
; O_*			Various sycall flags/modes.
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defconst "version", 0, WORD_VERSION, VERSION_NUM
 | 
						|
	defconst "wordbuf", 0, WORD_WORDBUF, word_buf
 | 
						|
	defconst "linesize", 0, WORD_LINESIZE, MAX_LINE_SIZE
 | 
						|
	defconst "f_immed", 0, WORD__F_IMMED, F_IMMED
 | 
						|
	defconst "f_hidden", 0, WORD__F_HIDDEN, F_HIDDEN
 | 
						|
	defconst "f_lenmask", 0, WORD__F_LENMASK, F_LENMASK
 | 
						|
	defconst "h_nsize", 0, WORD__H_NSIZE, H_NSIZE
 | 
						|
	defconst "h_name", 0, WORD__H_NAME, H_NAME
 | 
						|
	defconst "xt_body", 0, WORD__XT_BODY, XT_BODY
 | 
						|
	defconst "xt_length", 0, WORD__XT_LENGTH, XT_LENGTH
 | 
						|
	defconst "xt_compile", 0, WORD__XT_COMPILE, XT_COMPILE
 | 
						|
	defconst "xt_size", 0, WORD__XT_SIZE, XT_SIZE
 | 
						|
 | 
						|
	defconst "sys_exit", 0, WORD_SYS_EXIT, SYS_exit
 | 
						|
	defconst "sys_open", 0, WORD_SYS_OPEN, SYS_open
 | 
						|
	defconst "sys_close", 0, WORD_SYS_CLOSE, SYS_close
 | 
						|
	defconst "sys_read", 0, WORD_SYS_READ, SYS_read
 | 
						|
	defconst "sys_write", 0, WORD_SYS_WRITE, SYS_write
 | 
						|
	defconst "sys_unlink", 0, WORD_SYS_UNLINK, SYS_unlink
 | 
						|
	defconst "sys_rename", 0, WORD_SYS_RENAME, SYS_rename
 | 
						|
	defconst "sys_ftruncate", 0, WORD_SYS_FTRUNCATE, SYS_ftruncate
 | 
						|
	defconst "sys_fsync", 0, WORD_SYS_FSYNC, SYS_fsync
 | 
						|
	defconst "sys_lseek", 0, WORD_SYS_LSEEK, SYS_lseek
 | 
						|
	defconst "sys_fstat", 0, WORD_SYS_FSTAT, SYS_fstat
 | 
						|
	defconst "sys_stat", 0, WORD_SYS_STAT, SYS_stat
 | 
						|
 | 
						|
	defconst "o_rdonly", 0, WORD_O_RDONLY, 0x0
 | 
						|
	defconst "o_wronly", 0, WORD_O_WRONLY, 0x1
 | 
						|
	defconst "o_rdwr", 0, WORD_O_RDWR, 0x2
 | 
						|
	defconst "o_creat", 0, WORD_O_CREAT, 0x100
 | 
						|
	defconst "o_excl", 0, WORD_O_EXCL, 0x200
 | 
						|
	defconst "o_trunc", 0, WORD_O_TRUNC, 0x1000
 | 
						|
	defconst "o_append", 0, WORD_O_APPEND, 0x2000
 | 
						|
	defconst "o_nonblock", 0, WORD_O_NONBLOCK, 0x4000
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; data stack ordering words
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "dsp@", 0, WORD_DSPFETCH, WORD_INLINE_COMMA
 | 
						|
	PUSHDSP ebx
 | 
						|
	GETDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "dsp!", 0, WORD_DSPSTORE, WORD_INLINE_COMMA
 | 
						|
	SETDSP ebx
 | 
						|
	POPDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "drop", 0, WORD_DROP, WORD_INLINE_COMMA
 | 
						|
	POPDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "swap", 0, WORD_SWAP, WORD_INLINE_COMMA
 | 
						|
	xchg ebx, [ebp]
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "dup", 0, WORD_DUP, WORD_INLINE_COMMA
 | 
						|
	PUSHDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "over", 0, WORD_OVER, WORD_INLINE_COMMA
 | 
						|
	PUSHDSP ebx
 | 
						|
	PICKDSP ebx, 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "rot", 0, WORD_ROT, WORD_INLINE_COMMA
 | 
						|
	mov eax, ebx
 | 
						|
	PICKDSP ecx, 0
 | 
						|
	PICKDSP ebx, 4
 | 
						|
	PUTDSP eax, 0
 | 
						|
	PUTDSP ecx, 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "-rot", 0, WORD_NROT, WORD_INLINE_COMMA
 | 
						|
	mov eax, ebx
 | 
						|
	PICKDSP ebx, 0
 | 
						|
	PICKDSP ecx, 4
 | 
						|
	PUTDSP ecx, 0
 | 
						|
	PUTDSP eax, 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2drop", 0, WORD_DROP2, WORD_INLINE_COMMA
 | 
						|
	PICKDSP ebx, 4
 | 
						|
	ADDDSP 8
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2dup", 0, WORD_DUP2, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	ADDDSP -8
 | 
						|
	PUTDSP eax, 0
 | 
						|
	PUTDSP ebx, 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2swap", 0, WORD_SWAP2, WORD_INLINE_COMMA
 | 
						|
	mov eax, ebx
 | 
						|
	PICKDSP ecx, 0
 | 
						|
	PICKDSP ebx, 4
 | 
						|
	PICKDSP edx, 8
 | 
						|
	PUTDSP edx, 0
 | 
						|
	PUTDSP eax, 4
 | 
						|
	PUTDSP ecx, 8
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2rot", 0, WORD_ROT2, WORD_INLINE_COMMA
 | 
						|
	mov eax, ebx
 | 
						|
	PICKDSP ecx, 16
 | 
						|
	PICKDSP ebx, 12
 | 
						|
	PICKDSP edx, 8
 | 
						|
	PICKDSP edi, 4
 | 
						|
	PICKDSP esi, 0
 | 
						|
	PUTDSP edx, 16
 | 
						|
	PUTDSP edi, 12
 | 
						|
	PUTDSP esi, 8
 | 
						|
	PUTDSP eax, 4
 | 
						|
	PUTDSP ecx, 0
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "?dup", 0, WORD_QDUP, WORD_INLINE_COMMA
 | 
						|
	test ebx, ebx
 | 
						|
	if nz
 | 
						|
		PUSHDSP ebx
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "!?dup", 0, WORD_NQDUP, WORD_INLINE_COMMA
 | 
						|
	test ebx, ebx
 | 
						|
	if z
 | 
						|
		PUSHDSP ebx
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "nip", 0, WORD_NIP, WORD_INLINE_COMMA
 | 
						|
	ADDDSP 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "tuck", 0, WORD_TUCK, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	PUTDSP ebx, 0
 | 
						|
	PUSHDSP eax
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "pick", 0, WORD_PICK, WORD_INLINE_COMMA
 | 
						|
	mov ebx, [ebp + (ebx * 4)]
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2tuck", 0, WORD_TUCK2, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	PICKDSP ecx, 4
 | 
						|
	PICKDSP edx, 8
 | 
						|
	ADDDSP -8
 | 
						|
	PUTDSP eax, 0
 | 
						|
	PUTDSP ecx, 4
 | 
						|
	PUTDSP edx, 8
 | 
						|
	PUTDSP ebx, 12
 | 
						|
	PUTDSP eax, 16
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2nip", 0, WORD_NIP2, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	ADDDSP 8
 | 
						|
	PUTDSP eax, 0
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2over", 0, WORD_OVER2, WORD_INLINE_COMMA
 | 
						|
	ADDDSP -8
 | 
						|
	PUTDSP ebx, 4
 | 
						|
	PICKDSP ebx, 16
 | 
						|
	PUTDSP ebx, 0
 | 
						|
	PICKDSP ebx, 12
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; return stack ordering words
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword ">r", 0, WORD_TOR, WORD_INLINE_COMMA
 | 
						|
	TORSP
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "r>", 0, WORD_FROMR, WORD_INLINE_COMMA
 | 
						|
	FROMRSP
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2>r", 0, WORD_TOR2, WORD_INLINE_COMMA
 | 
						|
	ADDRSP -8
 | 
						|
	PICKDSP ecx, 0
 | 
						|
	PUTRSP ebx, 0
 | 
						|
	PUTRSP ecx, 4
 | 
						|
	PICKDSP ebx, 4
 | 
						|
	ADDDSP 8
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2r>", 0, WORD_FROMR2, WORD_INLINE_COMMA
 | 
						|
	ADDDSP -8
 | 
						|
	PUTDSP ebx, 4
 | 
						|
	PICKRSP ebx, 0
 | 
						|
	PICKRSP ecx, 4
 | 
						|
	PUTDSP ecx, 0
 | 
						|
	ADDRSP 8
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "rsp@", 0, WORD_RSPFETCH, WORD_INLINE_COMMA
 | 
						|
	PUSHDSP ebx
 | 
						|
	GETRSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "r@", 0, WORD_RFETCH, WORD_INLINE_COMMA
 | 
						|
	PUSHDSP ebx
 | 
						|
	PICKRSP ebx, 0
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "r!", 0, WORD_RSTORE, WORD_INLINE_COMMA
 | 
						|
	PUTRSP ebx, 0
 | 
						|
	POPDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2r@", 0, WORD_RFETCH2, WORD_INLINE_COMMA
 | 
						|
	ADDDSP -8
 | 
						|
	PUTDSP ebx, 4
 | 
						|
	PICKRSP ebx, 4
 | 
						|
	PICKRSP ecx, 0
 | 
						|
	PUTDSP ecx, 0
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "rsp!", 0, WORD_RSPSTORE, WORD_INLINE_COMMA
 | 
						|
	SETRSP ebx
 | 
						|
	POPDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "rdrop", 0, WORD_RDROP, WORD_INLINE_COMMA
 | 
						|
	ADDRSP 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2rdrop", 0, WORD_RDROP2, WORD_INLINE_COMMA
 | 
						|
	ADDRSP 8
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "n>r", 0, WORD_NTOR, WORD_CALL_COMMA
 | 
						|
	PUSHDSP ebx
 | 
						|
	PICKRSP eax, 0
 | 
						|
	mov ecx, ebx
 | 
						|
	inc ecx
 | 
						|
	neg ebx
 | 
						|
	lea esp, [esp + (ebx * 4)]
 | 
						|
	mov esi, ebp
 | 
						|
	mov edi, esp
 | 
						|
	rep movsd
 | 
						|
	mov ebp, esi
 | 
						|
	POPDSP ebx
 | 
						|
	jmp eax
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "nr>", 0, WORD_NFROMR, WORD_CALL_COMMA
 | 
						|
	PUSHDSP ebx
 | 
						|
	POPRSP eax
 | 
						|
	PICKRSP ebx, 0
 | 
						|
	inc ebx
 | 
						|
	mov ecx, ebx
 | 
						|
	neg ebx
 | 
						|
	lea ebp, [ebp + (ebx * 4)]
 | 
						|
	mov esi, esp
 | 
						|
	mov edi, ebp
 | 
						|
	rep movsd
 | 
						|
	mov esp, esi
 | 
						|
	POPDSP ebx
 | 
						|
	jmp eax
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; memory fetch and store words
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "!", 0, WORD_STORE, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	mov [ebx], eax
 | 
						|
	PICKDSP ebx, 4
 | 
						|
	ADDDSP 8
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "@", 0, WORD_FETCH, WORD_INLINE_COMMA
 | 
						|
	mov ebx, [ebx]
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "+!", 0, WORD_ADDSTORE, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	add [ebx], eax
 | 
						|
	PICKDSP ebx, 4
 | 
						|
	ADDDSP 8
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "-!", 0, WORD_SUBSTORE, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	sub [ebx], eax
 | 
						|
	PICKDSP ebx, 4
 | 
						|
	ADDDSP 8
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "c!", 0, WORD_STOREBYTE, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	mov [ebx], al
 | 
						|
	PICKDSP ebx, 4
 | 
						|
	ADDDSP 8
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "c+!", 0, WORD_ADDBYTE, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	add [ebx], al
 | 
						|
	PICKDSP ebx, 4
 | 
						|
	ADDDSP 8
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "c@", 0, WORD_FETCHBYTE, WORD_INLINE_COMMA
 | 
						|
	mov eax, ebx
 | 
						|
	xor ebx, ebx
 | 
						|
	mov bl, [eax]
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "w!", 0, WORD_STORESHORT, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	mov [ebx], ax
 | 
						|
	PICKDSP ebx, 4
 | 
						|
	ADDDSP 8
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "w@", 0, WORD_FETCHSHORT, WORD_INLINE_COMMA
 | 
						|
	mov eax, ebx
 | 
						|
	xor ebx, ebx
 | 
						|
	mov bx, [eax]
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2!", 0, WORD_STORE2, WORD_INLINE_COMMA
 | 
						|
	PICKDSP ecx, 4
 | 
						|
	PICKDSP edx, 0
 | 
						|
	mov [ebx + 4], ecx
 | 
						|
	mov [ebx], edx
 | 
						|
	PICKDSP ebx, 8
 | 
						|
	ADDDSP 12
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2@", 0, WORD_FETCH2, WORD_INLINE_COMMA
 | 
						|
	ADDDSP -4
 | 
						|
	mov ecx, [ebx +4]
 | 
						|
	mov ebx, [ebx]
 | 
						|
	PUTDSP ecx, 0
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "blank", 0, WORD_BLANK, WORD_CALL_COMMA
 | 
						|
	mov ecx, ebx
 | 
						|
	PICKDSP ebx, 4
 | 
						|
	PICKDSP edi, 0
 | 
						|
	ADDDSP 8
 | 
						|
	mov eax, 0x20
 | 
						|
	rep stosb
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "erase", 0, WORD_ERASE, WORD_CALL_COMMA
 | 
						|
	mov ecx, ebx
 | 
						|
	PICKDSP ebx, 4
 | 
						|
	PICKDSP edi, 0
 | 
						|
	ADDDSP 8
 | 
						|
	xor eax, eax
 | 
						|
	rep stosb
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "fill", 0, WORD_FILL, WORD_CALL_COMMA
 | 
						|
	mov eax, ebx
 | 
						|
	PICKDSP ebx, 8
 | 
						|
	PICKDSP edi, 4
 | 
						|
	PICKDSP ecx, 0
 | 
						|
	ADDDSP 12
 | 
						|
	rep stosb
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "cmove>", 0, WORD_CMOVEB, WORD_CALL_COMMA
 | 
						|
	mov ecx, ebx
 | 
						|
	PICKDSP ebx, 8
 | 
						|
	PICKDSP esi, 4
 | 
						|
	PICKDSP edi, 0
 | 
						|
	ADDDSP 12
 | 
						|
	lea esi, [esi + ecx - 1]
 | 
						|
	lea edi, [edi + ecx - 1]
 | 
						|
	std
 | 
						|
	rep movsb
 | 
						|
	cld
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "cmove", 0, WORD_CMOVE, WORD_CALL_COMMA
 | 
						|
	mov ecx, ebx
 | 
						|
	PICKDSP ebx, 8
 | 
						|
	PICKDSP esi, 4
 | 
						|
	PICKDSP edi, 0
 | 
						|
	ADDDSP 12
 | 
						|
	rep movsb
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "move", 0, WORD_MOVE, WORD_CALL_COMMA
 | 
						|
	mov ecx, ebx
 | 
						|
	PICKDSP ebx, 8
 | 
						|
	PICKDSP esi, 4
 | 
						|
	PICKDSP edi, 0
 | 
						|
	ADDDSP 12
 | 
						|
	cmp esi, edi
 | 
						|
	if a
 | 
						|
		rep movsb
 | 
						|
	else
 | 
						|
		lea esi, [esi + ecx -1]
 | 
						|
		lea edi, [edi + ecx -1]
 | 
						|
		std
 | 
						|
		rep movsb
 | 
						|
		cld
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; single precision alu words
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "+", 0, WORD_ADD, WORD_INLINE_COMMA
 | 
						|
	add ebx, [ebp]
 | 
						|
	ADDDSP 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "-", 0, WORD_SUB, WORD_INLINE_COMMA
 | 
						|
	mov eax, ebx
 | 
						|
	POPDSP ebx
 | 
						|
	sub ebx, eax
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "*", 0, WORD_MULL, WORD_INLINE_COMMA
 | 
						|
	imul ebx, [ebp]
 | 
						|
	ADDDSP 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "/", 0, WORD_DIV, WORD_INLINE_COMMA
 | 
						|
	POPDSP eax
 | 
						|
	cdq
 | 
						|
	idiv ebx
 | 
						|
	mov ebx, eax
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "mod", 0, WORD_MOD, WORD_INLINE_COMMA
 | 
						|
	POPDSP eax
 | 
						|
	cdq
 | 
						|
	idiv ebx
 | 
						|
	mov ebx, edx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "1+", 0, WORD_INCR, WORD_INLINE_COMMA
 | 
						|
	add ebx, byte 1
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "1-", 0, WORD_DECR, WORD_INLINE_COMMA
 | 
						|
	sub ebx, byte 1
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "4+", 0, WORD_INCR4, WORD_INLINE_COMMA
 | 
						|
	add ebx, byte 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "4-", 0, WORD_DECR4, WORD_INLINE_COMMA
 | 
						|
	sub ebx, byte 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2+", 0, WORD_INCR2, WORD_INLINE_COMMA
 | 
						|
	add ebx, byte 2
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2-", 0, WORD_DECR2, WORD_INLINE_COMMA
 | 
						|
	sub ebx, byte 2
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2*", 0, WORD_TWOMUL, WORD_INLINE_COMMA
 | 
						|
	shl ebx, byte 1
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "2/", 0, WORD_TWODIV, WORD_INLINE_COMMA
 | 
						|
	sar ebx, byte 1
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "abs", 0, WORD_ABS, WORD_INLINE_COMMA
 | 
						|
	mov eax, ebx
 | 
						|
	sar eax, byte 31
 | 
						|
	add ebx, eax
 | 
						|
	xor ebx, eax
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "min", 0, WORD_MIN, WORD_INLINE_COMMA
 | 
						|
	POPDSP eax
 | 
						|
	cmp ebx, eax
 | 
						|
	if g
 | 
						|
		mov ebx, eax
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "max", 0, WORD_MAX, WORD_INLINE_COMMA
 | 
						|
	POPDSP eax
 | 
						|
	cmp ebx, eax
 | 
						|
	if l
 | 
						|
		mov ebx, eax
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "lshift", 0, WORD_LSHIFT, WORD_INLINE_COMMA
 | 
						|
	mov ecx, ebx
 | 
						|
	POPDSP ebx
 | 
						|
	shl ebx, cl
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "rshift", 0, WORD_RSHIFT, WORD_INLINE_COMMA
 | 
						|
	mov ecx, ebx
 | 
						|
	POPDSP ebx
 | 
						|
	shr ebx, cl
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "and", 0, WORD_AND, WORD_INLINE_COMMA
 | 
						|
	and ebx, [ebp]
 | 
						|
	ADDDSP 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "or", 0, WORD_OR, WORD_INLINE_COMMA
 | 
						|
	or ebx, [ebp]
 | 
						|
	ADDDSP 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "xor", 0, WORD_XOR, WORD_INLINE_COMMA
 | 
						|
	xor ebx, [ebp]
 | 
						|
	ADDDSP 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "negate", 0, WORD_NEGATE, WORD_INLINE_COMMA
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "invert", 0, WORD_INVERT, WORD_INLINE_COMMA
 | 
						|
	not ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; single precision comparision words
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "=", 0, WORD_EQ, WORD_INLINE_COMMA
 | 
						|
	cmp [ebp], ebx
 | 
						|
	sete bl
 | 
						|
	ADDDSP 4
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "<>", 0, WORD_NE, WORD_INLINE_COMMA
 | 
						|
	cmp [ebp], ebx
 | 
						|
	setne bl
 | 
						|
	ADDDSP 4
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "<", 0, WORD_LT, WORD_INLINE_COMMA
 | 
						|
	cmp [ebp], ebx
 | 
						|
	setl bl
 | 
						|
	ADDDSP 4
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword ">", 0, WORD_GT, WORD_INLINE_COMMA
 | 
						|
	cmp [ebp], ebx
 | 
						|
	setg bl
 | 
						|
	ADDDSP 4
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "u<", 0, WORD_ULT, WORD_INLINE_COMMA
 | 
						|
	cmp [ebp], ebx
 | 
						|
	setb bl
 | 
						|
	ADDDSP 4
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "u>", 0, WORD_UGT, WORD_INLINE_COMMA
 | 
						|
	cmp [ebp], ebx
 | 
						|
	seta bl
 | 
						|
	ADDDSP 4
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "u<=", 0, WORD_ULTEQ, WORD_INLINE_COMMA
 | 
						|
	cmp [ebp], ebx
 | 
						|
	setbe bl
 | 
						|
	ADDDSP 4
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "u>=", 0, WORD_UGTEQ, WORD_INLINE_COMMA
 | 
						|
	cmp [ebp], ebx
 | 
						|
	setae bl
 | 
						|
	ADDDSP 4
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "<=", 0, WORD_LTEQ, WORD_INLINE_COMMA
 | 
						|
	cmp [ebp], ebx
 | 
						|
	setle bl
 | 
						|
	ADDDSP 4
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword ">=", 0, WORD_GTEQ, WORD_INLINE_COMMA
 | 
						|
	cmp [ebp], ebx
 | 
						|
	setge bl
 | 
						|
	ADDDSP 4
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "0=", 0, WORD_ZEQ, WORD_INLINE_COMMA
 | 
						|
	test ebx, ebx
 | 
						|
	setz bl
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "0<>", 0, WORD_ZNE, WORD_INLINE_COMMA
 | 
						|
	test ebx, ebx
 | 
						|
	setnz bl
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "0<", 0, WORD_ZLT, WORD_INLINE_COMMA
 | 
						|
	test ebx, ebx
 | 
						|
	setl bl
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "0>", 0, WORD_ZGT, WORD_INLINE_COMMA
 | 
						|
	test ebx, ebx
 | 
						|
	setg bl
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "0<=", 0, WORD_ZLTEQ, WORD_INLINE_COMMA
 | 
						|
	test ebx, ebx
 | 
						|
	setle bl
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "0>=", 0, WORD_ZGTEQ, WORD_INLINE_COMMA
 | 
						|
	test ebx, ebx
 | 
						|
	setge bl
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; double precision ALU words
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "s>d", 0, WORD_STOD, WORD_INLINE_COMMA
 | 
						|
	mov eax, ebx
 | 
						|
	cdq
 | 
						|
	PUSHDSP eax
 | 
						|
	mov ebx, edx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "d>s", 0, WORD_DTOS, WORD_INLINE_COMMA
 | 
						|
	POPDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "d+", 0, WORD_DPLUS, WORD_INLINE_COMMA
 | 
						|
	PICKDSP ecx, 8
 | 
						|
	PICKDSP edx, 4
 | 
						|
	PICKDSP eax, 0
 | 
						|
	add eax, ecx
 | 
						|
	adc ebx, edx
 | 
						|
	PUTDSP eax, 8
 | 
						|
	ADDDSP 8
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "d-", 0, WORD_DMINUS, WORD_INLINE_COMMA
 | 
						|
	PICKDSP ecx, 8
 | 
						|
	PICKDSP edx, 4
 | 
						|
	PICKDSP eax, 0
 | 
						|
	sub ecx, eax
 | 
						|
	sbb edx, ebx
 | 
						|
	PUTDSP ecx, 8
 | 
						|
	mov ebx, edx
 | 
						|
	ADDDSP 8
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "d2*", 0, WORD_D2STAR, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	shl eax, 1
 | 
						|
	rcl ebx, 1
 | 
						|
	PUTDSP eax, 0
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "d2/", 0, WORD_D2SLASH, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	sar ebx, 1
 | 
						|
	rcr eax, 1
 | 
						|
	PUTDSP eax, 0
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "*/", 0, WORD_MULDIV, WORD_INLINE_COMMA
 | 
						|
	PICKDSP edx, 4
 | 
						|
	PICKDSP eax, 0
 | 
						|
	imul edx
 | 
						|
	idiv ebx
 | 
						|
	mov ebx, eax
 | 
						|
	ADDDSP 8
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "*/mod", 0, WORD_STARSMOD, WORD_INLINE_COMMA
 | 
						|
	PICKDSP edx, 4
 | 
						|
	PICKDSP eax, 0
 | 
						|
	imul edx
 | 
						|
	idiv ebx
 | 
						|
	PUTDSP edx, 4
 | 
						|
	ADDDSP 4
 | 
						|
	mov ebx, eax
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "/mod", 0, WORD_DIVMOD, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	cdq
 | 
						|
	idiv ebx
 | 
						|
	PUTDSP edx, 0
 | 
						|
	mov ebx, eax
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "dnegate", 0, WORD_DNEGATE, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	not eax
 | 
						|
	not ebx
 | 
						|
	add eax, 1
 | 
						|
	adc ebx, 0
 | 
						|
	PUTDSP eax, 0
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "dabs", 0, WORD_DABS, WORD_INLINE_COMMA
 | 
						|
	test ebx, ebx
 | 
						|
	if l
 | 
						|
		PICKDSP eax, 0
 | 
						|
		not eax
 | 
						|
		not ebx
 | 
						|
		add eax, 1
 | 
						|
		adc ebx, 0
 | 
						|
		PUTDSP eax, 0
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "dmax", 0, WORD_DMAX, WORD_INLINE_COMMA
 | 
						|
	PICKDSP ecx, 8
 | 
						|
	PICKDSP edx, 4
 | 
						|
	PICKDSP eax, 0
 | 
						|
	ADDDSP 8
 | 
						|
	mov esi, ecx
 | 
						|
	mov edi, edx
 | 
						|
	sub esi, eax
 | 
						|
	sbb edi, ebx
 | 
						|
	if l
 | 
						|
		PUTDSP eax, 0
 | 
						|
	else
 | 
						|
		mov ebx, edx
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "dmin", 0, WORD_DMIN, WORD_INLINE_COMMA
 | 
						|
	PICKDSP ecx, 8
 | 
						|
	PICKDSP edx, 4
 | 
						|
	PICKDSP eax, 0
 | 
						|
	ADDDSP 8
 | 
						|
	mov esi, ecx
 | 
						|
	mov edi, edx
 | 
						|
	sub esi, eax
 | 
						|
	sbb edi, ebx
 | 
						|
	if ge
 | 
						|
		PUTDSP eax, 0
 | 
						|
	else
 | 
						|
		mov ebx, edx
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; double precision comparision words
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "d0=", 0, WORD_DZEQ, WORD_INLINE_COMMA
 | 
						|
	or ebx, [ebp]
 | 
						|
	setz bl
 | 
						|
	ADDDSP 4
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "d0<>", 0, WORD_DZNEQ, WORD_INLINE_COMMA
 | 
						|
	or ebx, [ebp]
 | 
						|
	setnz bl
 | 
						|
	ADDDSP 4
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "d0<", 0, WORD_DZLT, WORD_INLINE_COMMA
 | 
						|
	test ebx, ebx
 | 
						|
	setl bl
 | 
						|
	ADDDSP 4
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "d=", 0, WORD_DEQ, WORD_INLINE_COMMA
 | 
						|
	PICKDSP ecx, 8
 | 
						|
	PICKDSP eax, 4
 | 
						|
	sub ecx, [ebp]
 | 
						|
	sbb eax, ebx
 | 
						|
	setz bl
 | 
						|
	ADDDSP 12
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "d<>", 0, WORD_DNEQ, WORD_INLINE_COMMA
 | 
						|
	PICKDSP ecx, 8
 | 
						|
	PICKDSP eax, 4
 | 
						|
	sub ecx, [ebp]
 | 
						|
	sbb eax, ebx
 | 
						|
	setnz bl
 | 
						|
	ADDDSP 12
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "d<", 0, WORD_DLT, WORD_INLINE_COMMA
 | 
						|
	PICKDSP ecx, 8
 | 
						|
	PICKDSP eax, 4
 | 
						|
	sub ecx, [ebp]
 | 
						|
	sbb eax, ebx
 | 
						|
	setl bl
 | 
						|
	ADDDSP 12
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "du<", 0, WORD_DULT, WORD_INLINE_COMMA
 | 
						|
	PICKDSP ecx, 8
 | 
						|
	PICKDSP eax, 4
 | 
						|
	sub ecx, [ebp]
 | 
						|
	sbb eax, ebx
 | 
						|
	setb bl
 | 
						|
	ADDDSP 12
 | 
						|
	movzx ebx, bl
 | 
						|
	neg ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; mixed precision words
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "m+", 0, WORD_MPLUS, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 4
 | 
						|
	PICKDSP edx, 0
 | 
						|
	add eax, ebx
 | 
						|
	adc edx, 0
 | 
						|
	PUTDSP eax, 4
 | 
						|
	mov ebx, edx
 | 
						|
	ADDDSP 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "m-", 0, WORD_MMINUS, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 4
 | 
						|
	PICKDSP edx, 0
 | 
						|
	sub eax, ebx
 | 
						|
	sbb edx, 0
 | 
						|
	PUTDSP eax, 4
 | 
						|
	mov ebx, edx
 | 
						|
	ADDDSP 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "m*", 0, WORD_MULSTAR, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	imul ebx
 | 
						|
	PUTDSP eax, 0
 | 
						|
	mov ebx, edx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "m/", 0, WORD_MSLASH, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 4
 | 
						|
	PICKDSP edx, 0
 | 
						|
	idiv ebx
 | 
						|
	mov ebx, eax
 | 
						|
	ADDDSP 8
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "um*", 0, WORD_UMULSTAR, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 0
 | 
						|
	mul ebx
 | 
						|
	PUTDSP eax, 0
 | 
						|
	mov ebx, edx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "um/mod", 0, WORD_UMDIVMOD, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 4
 | 
						|
	PICKDSP edx, 0
 | 
						|
	div ebx
 | 
						|
	PUTDSP edx, 4
 | 
						|
	mov ebx, eax
 | 
						|
	ADDDSP 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "fm/mod", 0, WORD_FMDIVMOD, WORD_INLINE_COMMA
 | 
						|
	PICKDSP edx, 0
 | 
						|
	PICKDSP eax, 4
 | 
						|
	mov ecx, ebx
 | 
						|
	ADDDSP 4
 | 
						|
	xor ecx, edx
 | 
						|
	idiv ebx
 | 
						|
	test ecx, ecx
 | 
						|
	if s
 | 
						|
		test edx, edx
 | 
						|
		if nz
 | 
						|
			dec eax
 | 
						|
			add edx, ebx
 | 
						|
		endif
 | 
						|
	endif
 | 
						|
	PUTDSP edx, 0
 | 
						|
	mov ebx, eax
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "sm/rem", 0, WORD_SMDIVREM, WORD_INLINE_COMMA
 | 
						|
	PICKDSP eax, 4
 | 
						|
	PICKDSP edx, 0
 | 
						|
	idiv ebx
 | 
						|
	PUTDSP edx, 4
 | 
						|
	mov ebx, eax
 | 
						|
	ADDDSP 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "u/mod", 0, WORD_UDIVMOD, WORD_INLINE_COMMA
 | 
						|
	xor edx, edx
 | 
						|
	PICKDSP eax, 0
 | 
						|
	div ebx
 | 
						|
	PUTDSP edx, 0
 | 
						|
	mov ebx, eax
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "dm*", 0, WORD_DMULSTAR, WORD_CALL_COMMA
 | 
						|
	call WORD_TUCK
 | 
						|
	call WORD_MULL
 | 
						|
	TORSP
 | 
						|
	call WORD_UMULSTAR
 | 
						|
	FROMRSP
 | 
						|
	call WORD_ADD
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;
 | 
						|
; control flow words
 | 
						|
;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "branch", 0, WORD_BRANCH, WORD_INLINE_COMMA
 | 
						|
i_jmp:
 | 
						|
	jmp strict near i_ret
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "0branch", 0, WORD_ZBRANCH, WORD_INLINE_COMMA
 | 
						|
	mov eax, ebx
 | 
						|
	POPDSP ebx
 | 
						|
	test eax, eax
 | 
						|
	jz strict near i_jmp
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "exit", 0, WORD_EXIT, WORD_EXIT_COMMA
 | 
						|
i_ret:
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "exit,", 0, WORD_EXIT_COMMA, WORD_CALL_COMMA
 | 
						|
	mov edi, [var_WORD_DP]
 | 
						|
	sub edi, 5
 | 
						|
	cmp edi, [lastcall]	; are we just after a call instruction ?
 | 
						|
	if z
 | 
						|
		mov al, [i_jmp]
 | 
						|
		mov [edi], al	; change it to a jmp
 | 
						|
	endif
 | 
						|
	mov edi, [var_WORD_DP]
 | 
						|
	mov al, [i_ret]
 | 
						|
	stosb
 | 
						|
	mov [var_WORD_DP], edi
 | 
						|
	POPDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "execute", 0, WORD_EXECUTE, WORD_CALL_COMMA
 | 
						|
	mov eax, ebx	; Get xt into eax
 | 
						|
	POPDSP ebx		; After xt runs its ret will continue executing the current word.
 | 
						|
	jmp eax			; and jump to it.
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; terminal input words
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "read-char", 0, WORD_READCHAR, WORD_CALL_COMMA
 | 
						|
	mov ecx, var_WORD_CHARBUF	; 2nd param: buffer
 | 
						|
	mov edx, 1					; 3rd param: max length
 | 
						|
	push edx
 | 
						|
	push ecx
 | 
						|
	push ebx
 | 
						|
	mov eax, SYS_read			; syscall: read
 | 
						|
	call _syscall
 | 
						|
	add esp, 12
 | 
						|
	xor ebx, ebx
 | 
						|
	test eax, eax
 | 
						|
	if be
 | 
						|
		mov ebx, -1
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "read-line", 0, WORD_READLINE, WORD_CALL_COMMA
 | 
						|
	call WORD_NROT
 | 
						|
	call WORD_OVER
 | 
						|
	call WORD_ADD
 | 
						|
	call WORD_OVER		; ( fd start end cur )
 | 
						|
readline_l1:
 | 
						|
	PICKDSP eax, 0
 | 
						|
	cmp ebx, eax
 | 
						|
	jz readline_l4
 | 
						|
	PUSHDSP ebx
 | 
						|
	PICKDSP ebx, 12
 | 
						|
	call WORD_READCHAR
 | 
						|
	test ebx, ebx
 | 
						|
	jz readline_l2
 | 
						|
	call WORD_DROP
 | 
						|
	call WORD_DROP2
 | 
						|
	call WORD_DROP2
 | 
						|
	LOADTOS 0
 | 
						|
	LOADTOS 0
 | 
						|
	LOADTOS -1
 | 
						|
	jmp readline_l5
 | 
						|
readline_l2:
 | 
						|
	mov ebx, [var_WORD_CHARBUF]
 | 
						|
	cmp ebx, 10			; LF
 | 
						|
	jz readline_l3
 | 
						|
	call WORD_OVER
 | 
						|
	call WORD_STOREBYTE
 | 
						|
	call WORD_INCR
 | 
						|
	jmp readline_l1
 | 
						|
readline_l3:
 | 
						|
	call WORD_DROP
 | 
						|
readline_l4:
 | 
						|
	call WORD_NIP
 | 
						|
	call WORD_SWAP
 | 
						|
	call WORD_SUB
 | 
						|
	call WORD_NIP
 | 
						|
	LOADTOS -1
 | 
						|
	LOADTOS 0
 | 
						|
readline_l5:
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "key", 0, WORD_KEY, WORD_CALL_COMMA
 | 
						|
	PUSHDSP ebx
 | 
						|
	xor ebx, ebx		; stdin
 | 
						|
	call WORD_READCHAR
 | 
						|
	mov ebx, [var_WORD_CHARBUF]
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "accept", 0, WORD_ACCEPT, WORD_CALL_COMMA
 | 
						|
	call WORD_OVER
 | 
						|
	call WORD_ADD
 | 
						|
	call WORD_OVER	; ( start end cur )
 | 
						|
accept_l1:
 | 
						|
	call WORD_KEY
 | 
						|
	cmp ebx, 127	; BS
 | 
						|
	jz accept_l2
 | 
						|
	cmp ebx, 10		; LF
 | 
						|
	jz accept_l3
 | 
						|
	call WORD_OVER	; ( start end cur key cur )
 | 
						|
	call WORD_STOREBYTE
 | 
						|
	call WORD_INCR	; ( start end cur' )
 | 
						|
	PICKDSP eax, 0
 | 
						|
	cmp ebx, eax
 | 
						|
	jz accept_l4
 | 
						|
	jmp accept_l1
 | 
						|
accept_l2:
 | 
						|
	PICKDSP eax, 4	; ( start end cur' )
 | 
						|
	cmp ebx, eax
 | 
						|
	jz accept_l1
 | 
						|
	call WORD_DECR
 | 
						|
	jmp accept_l1
 | 
						|
accept_l3:
 | 
						|
	call WORD_DROP	; ( start end cur' )
 | 
						|
accept_l4:
 | 
						|
	call WORD_NIP
 | 
						|
	call WORD_SWAP
 | 
						|
	call WORD_SUB
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "tabs>spaces", 0, WORD_TABSTOSPACES, WORD_CALL_COMMA
 | 
						|
	mov ecx, ebx
 | 
						|
	POPDSP esi
 | 
						|
	test ecx, ecx
 | 
						|
	if nz
 | 
						|
		repeat
 | 
						|
			lodsb
 | 
						|
			cmp al, 9	;TAB
 | 
						|
			if z
 | 
						|
				mov byte [esi - 1], ' '
 | 
						|
			endif
 | 
						|
			dec ecx
 | 
						|
		until z
 | 
						|
	endif
 | 
						|
	POPDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; terminal output words
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "type-fd", 0, WORD_TYPE_FD, WORD_CALL_COMMA
 | 
						|
	PICKDSP edx, 0			; 3rd param: length of string
 | 
						|
	PICKDSP ecx, 4			; 2nd param: address of string
 | 
						|
	ADDDSP 8				; 1st param: FD in ebx
 | 
						|
	mov eax, SYS_write		; write syscall
 | 
						|
	push edx
 | 
						|
	push ecx
 | 
						|
	push ebx
 | 
						|
	call _syscall
 | 
						|
	add esp, 12
 | 
						|
	POPDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "type", 0, WORD_TYPE, WORD_CALL_COMMA
 | 
						|
	LOADTOS 1				; stdout
 | 
						|
	call WORD_TYPE_FD
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "emit", 0, WORD_EMIT, WORD_CALL_COMMA
 | 
						|
	mov [emit_scratch], bl	; write needs the address of the byte to write
 | 
						|
	mov ebx, emit_scratch
 | 
						|
	LOADTOS 1
 | 
						|
	call WORD_TYPE
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;
 | 
						|
; system call words
 | 
						|
;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "syscall", 0, WORD_SYSCALL, WORD_CALL_COMMA
 | 
						|
	pop eax
 | 
						|
	mov [syscallret], eax	; save return address
 | 
						|
	mov eax, ebx			; System call number (see <asm/unistd.h>)
 | 
						|
	call _syscall
 | 
						|
	mov ebx, eax			; Result (negative for -errno)
 | 
						|
	jmp [syscallret]		; return to caller
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "lsyscall", 0, WORD_LSYSCALL, WORD_CALL_COMMA
 | 
						|
	pop eax
 | 
						|
	mov [syscallret], eax	; save return address
 | 
						|
	mov eax, ebx			; System call number (see <asm/unistd.h>)
 | 
						|
	call _lsyscall
 | 
						|
	PUSHDSP eax
 | 
						|
	mov ebx, edx			; Result (negative for -errno)
 | 
						|
	jmp [syscallret]		; return to caller
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;
 | 
						|
; string words
 | 
						|
;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "count", 0, WORD_COUNT, WORD_CALL_COMMA
 | 
						|
	xor eax, eax
 | 
						|
	mov al, [ebx]
 | 
						|
	inc ebx
 | 
						|
	LOADTOS eax
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "-trailing", 0, WORD_TRAILING, WORD_CALL_COMMA
 | 
						|
	test ebx, ebx
 | 
						|
	if nz
 | 
						|
		PICKDSP esi, 0
 | 
						|
		mov ecx, ebx
 | 
						|
		add esi, ebx
 | 
						|
		dec esi
 | 
						|
		std
 | 
						|
	trailing_l1:
 | 
						|
		lodsb
 | 
						|
		cmp al, ' '
 | 
						|
		if be
 | 
						|
			loop trailing_l1
 | 
						|
		endif
 | 
						|
		mov ebx, ecx
 | 
						|
		cld
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "/string", 0, WORD_SSTRING, WORD_CALL_COMMA
 | 
						|
	mov eax, ebx
 | 
						|
	POPDSP ebx
 | 
						|
	PICKDSP ecx, 0
 | 
						|
	sub ebx, eax
 | 
						|
	add ecx, eax
 | 
						|
	PUTDSP ecx, 0
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "compare", 0, WORD_COMPARE, WORD_CALL_COMMA
 | 
						|
	PICKDSP esi, 8
 | 
						|
	PICKDSP edx, 4
 | 
						|
	PICKDSP edi, 0
 | 
						|
	ADDDSP 12
 | 
						|
	mov ecx, ebx
 | 
						|
	cmp edx, ebx
 | 
						|
	if be
 | 
						|
		mov ecx, edx
 | 
						|
	endif
 | 
						|
	test ecx, ecx		; ecx lowest length
 | 
						|
	jnz compare_l2
 | 
						|
	cmp edx, ebx
 | 
						|
	jz compare_l3		; both are 0 length
 | 
						|
	jmp compare_l4		; otherwise the longest wins
 | 
						|
compare_l2:
 | 
						|
	cmpsb
 | 
						|
	jnz compare_l4		; chars not same
 | 
						|
	loop compare_l2
 | 
						|
	cmp edx, ebx		; all chars same
 | 
						|
	jnz compare_l4		; strings not same size
 | 
						|
compare_l3:
 | 
						|
	xor ebx, ebx		; same
 | 
						|
	jmp compare_l7
 | 
						|
compare_l4:
 | 
						|
	ja compare_l6
 | 
						|
compare_l5:
 | 
						|
	mov ebx, -1
 | 
						|
	jmp compare_l7
 | 
						|
compare_l6:
 | 
						|
	mov ebx, 1
 | 
						|
compare_l7:
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "icompare", 0, WORD_COMPAREI, WORD_CALL_COMMA
 | 
						|
	PICKDSP esi, 8
 | 
						|
	PICKDSP edx, 4
 | 
						|
	PICKDSP edi, 0
 | 
						|
	ADDDSP 12
 | 
						|
	mov ecx, ebx
 | 
						|
	cmp edx, ebx
 | 
						|
	if be
 | 
						|
		mov ecx, edx
 | 
						|
	endif
 | 
						|
	test ecx, ecx		; ecx lowest length
 | 
						|
	jnz comparei_l2
 | 
						|
	cmp edx, ebx
 | 
						|
	jz comparei_l3		; both are 0 length
 | 
						|
	jmp comparei_l4		; otherwise the longest wins
 | 
						|
comparei_l2:
 | 
						|
	mov al, [esi]
 | 
						|
	mov ah, [edi]
 | 
						|
	to_lower al
 | 
						|
	to_lower ah
 | 
						|
	cmp ah, al
 | 
						|
	jnz comparei_l4		; chars not same
 | 
						|
	inc edi
 | 
						|
	inc esi
 | 
						|
	loop comparei_l2
 | 
						|
	cmp edx, ebx		; all chars same
 | 
						|
	jnz comparei_l4		; strings not same size
 | 
						|
comparei_l3:
 | 
						|
	xor ebx, ebx		; same
 | 
						|
	jmp comparei_l7
 | 
						|
comparei_l4:
 | 
						|
	ja comparei_l6
 | 
						|
comparei_l5:
 | 
						|
	mov ebx, -1
 | 
						|
	jmp comparei_l7
 | 
						|
comparei_l6:
 | 
						|
	mov ebx, 1
 | 
						|
comparei_l7:
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; dictionary searching words
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "find", 0, WORD_FIND, WORD_CALL_COMMA
 | 
						|
	call WORD_DUP
 | 
						|
	call WORD_COUNT
 | 
						|
	call WORD_FIND_DICT
 | 
						|
	test ebx, ebx
 | 
						|
	if nz
 | 
						|
		mov dl, [ebx + H_NSIZE]
 | 
						|
		call WORD_TCFA
 | 
						|
		LOADTOS 1
 | 
						|
		and edx, F_IMMED
 | 
						|
		if z
 | 
						|
			neg ebx
 | 
						|
		endif
 | 
						|
		call WORD_ROT
 | 
						|
		call WORD_DROP
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "(find)", 0, WORD_FIND_DICT, WORD_CALL_COMMA
 | 
						|
	mov ecx, ebx			; ecx = length
 | 
						|
	POPDSP edi				; edi = address
 | 
						|
	PUSHRSP ecx
 | 
						|
	mov esi, edi
 | 
						|
	call strhashi
 | 
						|
	and ebx, NUM_HASH_CHAINS-1
 | 
						|
	mov esi, hash_buckets
 | 
						|
	mov edx, [esi + (ebx * 4)]
 | 
						|
	POPRSP ecx				; edx can now scan back through this hash chain
 | 
						|
findd_l1:
 | 
						|
	test edx, edx			; NULL pointer?  (end of the linked list)
 | 
						|
	je findd_l4
 | 
						|
	xor eax, eax
 | 
						|
	mov al, [edx + H_NSIZE]	; al = flags+length field
 | 
						|
	and al, (F_HIDDEN|F_LENMASK)	; al = name length
 | 
						|
	cmp al, cl				; Length is the same?
 | 
						|
	jne findd_l2
 | 
						|
	PUSHRSP ecx				; Save the length
 | 
						|
	PUSHRSP edi				; Save the address (repe cmpsb will move this pointer)
 | 
						|
	lea esi, [edx + H_NAME]	; Dictionary string we are checking against.
 | 
						|
	call strcmpi
 | 
						|
	POPRSP edi
 | 
						|
	POPRSP ecx
 | 
						|
	jne findd_l2			; Not the same.
 | 
						|
	mov ebx, edx
 | 
						|
	ret
 | 
						|
findd_l2:
 | 
						|
	mov edx, [edx + H_HLINK]	; Move back through the link field to the previous word
 | 
						|
	jmp findd_l1			; .. and loop.
 | 
						|
findd_l4:
 | 
						|
	xor ebx, ebx			; Return zero to indicate not found.
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword ">cfa", 0, WORD_TCFA, WORD_CALL_COMMA
 | 
						|
	add ebx, H_NSIZE
 | 
						|
	mov al, [ebx]			; Load flags+len into al.
 | 
						|
	inc ebx					; skip flags+len byte.
 | 
						|
	and eax, F_LENMASK		; Just the length, not the flags.
 | 
						|
	add ebx, eax			; skip the name
 | 
						|
	add ebx, XT_SIZE		; skip to the xt
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "(bucket)", 0, WORD_BUCKET, WORD_CALL_COMMA
 | 
						|
	mov ecx, ebx		; ecx = length
 | 
						|
	POPDSP ebx			; ebx = address of name
 | 
						|
	PUSHRSP esi
 | 
						|
	mov esi, ebx
 | 
						|
	call strhashi
 | 
						|
	and ebx, NUM_HASH_CHAINS-1
 | 
						|
	mov esi, hash_buckets
 | 
						|
	lea ebx, [esi + (ebx * 4)]
 | 
						|
	POPRSP esi
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "unused", 0, WORD_UNUSED, WORD_CALL_COMMA
 | 
						|
	LOADTOS forth_end
 | 
						|
	LOADTOS [var_WORD_DP]
 | 
						|
	call WORD_SUB
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; dictionary building words
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "align", 0, WORD_ALIGNDP, WORD_CALL_COMMA
 | 
						|
	mov eax, [var_WORD_DP]
 | 
						|
	ALIGNREG eax
 | 
						|
	mov [var_WORD_DP], eax
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "header,", 0, WORD_HEADER_COMMA, WORD_CALL_COMMA
 | 
						|
	mov ecx, ebx				; ecx = length
 | 
						|
	POPDSP ebx					; ebx = address of name
 | 
						|
	call WORD_ALIGNDP			; align header
 | 
						|
	mov edi, [var_WORD_DP]		; edi is the address of the header
 | 
						|
	mov eax, [var_WORD_LATEST]	; Get link pointer
 | 
						|
	mov [edi + H_LLINK], eax	; and store it in the header.
 | 
						|
	mov [var_WORD_LATEST], edi
 | 
						|
	PUSHRSP ebx					; hash chain
 | 
						|
	PUSHRSP ecx
 | 
						|
	mov esi, ebx
 | 
						|
	call strhashi
 | 
						|
	and ebx, NUM_HASH_CHAINS-1
 | 
						|
	mov esi, hash_buckets
 | 
						|
	mov eax, [esi + (ebx * 4)]
 | 
						|
	mov [esi + (ebx * 4)], edi
 | 
						|
	mov [edi + H_HLINK], eax	; and store it in the header.
 | 
						|
	POPRSP ecx
 | 
						|
	POPRSP esi
 | 
						|
	mov [edi + H_NSIZE], cl		; Store the length/flags byte.
 | 
						|
	add edi, H_NAME
 | 
						|
	call strcpyi
 | 
						|
	mov ecx, XT_SIZE
 | 
						|
	xor eax, eax
 | 
						|
	rep stosb					; clear the gap till the xt
 | 
						|
	mov [var_WORD_DP], edi
 | 
						|
	mov long [edi + XT_COMPILE], WORD_CALL_COMMA	;compile action
 | 
						|
	POPDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "lit,", 0, WORD_LIT_COMMA, WORD_CALL_COMMA
 | 
						|
	mov esi, litc_l1
 | 
						|
	mov edi, [var_WORD_DP]
 | 
						|
	mov ecx, litc_l2 - litc_l1 - 4
 | 
						|
	rep movsb
 | 
						|
	mov [var_WORD_DP], edi
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
litc_l1:
 | 
						|
	LOADTOS 0xBAADF00D
 | 
						|
litc_l2:
 | 
						|
 | 
						|
	defword "slits", 0, WORD_SLITS, WORD_CALL_COMMA
 | 
						|
	PUSHDSP ebx
 | 
						|
	POPRSP esi
 | 
						|
	xor eax, eax
 | 
						|
	lodsb				; get the length of the string
 | 
						|
	PUSHDSP esi			; push the address of the start of the string
 | 
						|
	mov ebx, eax		; push length on the stack
 | 
						|
	add esi, eax		; skip past the string
 | 
						|
 	jmp esi
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "clits", 0, WORD_CLITS, WORD_CALL_COMMA
 | 
						|
	FROMRSP
 | 
						|
	xor eax, eax
 | 
						|
	mov al, [ebx]
 | 
						|
	lea eax, [ebx + eax + 1]
 | 
						|
 	jmp eax
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword ",", 0, WORD_COMMA, WORD_CALL_COMMA
 | 
						|
	mov edi, [var_WORD_DP]	; DP
 | 
						|
	mov eax, ebx
 | 
						|
	stosd					; Store it.
 | 
						|
	mov [var_WORD_DP], edi	; Update DP (incremented)
 | 
						|
	POPDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "c,", 0, WORD_CHAR_COMMA, WORD_CALL_COMMA
 | 
						|
	mov eax, ebx
 | 
						|
	mov edi, [var_WORD_DP]	; DP
 | 
						|
	stosb					; Store it.
 | 
						|
	mov [var_WORD_DP], edi	; Update DP (incremented)
 | 
						|
	POPDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword ":", 0, WORD_COLON, WORD_CALL_COMMA
 | 
						|
	call WORD_PARSENAME
 | 
						|
	call WORD_HEADER_COMMA	; Create the dictionary entry / header
 | 
						|
	mov eax, [var_WORD_DP]
 | 
						|
	mov [eax + XT_BODY], eax
 | 
						|
	call WORD_LATEST
 | 
						|
	call WORD_FETCH
 | 
						|
	call WORD_HIDDEN		; Make the word hidden
 | 
						|
	call WORD_RBRAC			; Go into compile mode.
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "create", 0, WORD_CREATE, WORD_CALL_COMMA
 | 
						|
	call WORD_PARSENAME
 | 
						|
	call WORD_HEADER_COMMA
 | 
						|
	mov esi, create_l1
 | 
						|
	mov edi, [var_WORD_DP]
 | 
						|
	PUSHRSP edi
 | 
						|
	mov ecx, create_l4 - create_l1
 | 
						|
	rep movsb
 | 
						|
	mov [var_WORD_DP], edi
 | 
						|
	mov edx, edi
 | 
						|
	call WORD_ALIGNDP
 | 
						|
	POPRSP eax
 | 
						|
	mov edi, [var_WORD_DP]
 | 
						|
	sub edx, eax
 | 
						|
	mov [eax + create_l2 - create_l1 - 4], edi
 | 
						|
	mov [eax + XT_BODY], edi
 | 
						|
	mov [eax + XT_LENGTH], edx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
create_l1:
 | 
						|
	LOADTOS 0xBAADF00D
 | 
						|
create_l2:
 | 
						|
	call strict near create_l3
 | 
						|
create_l3:
 | 
						|
	ret
 | 
						|
create_l4:
 | 
						|
 | 
						|
	defword "dodoes", 0, WORD_DODOES, WORD_CALL_COMMA
 | 
						|
	call WORD_LATEST
 | 
						|
	call WORD_FETCH
 | 
						|
	call WORD_TCFA
 | 
						|
	add ebx, create_l3 - create_l1 - 4
 | 
						|
	POPDSP eax
 | 
						|
	sub eax, ebx
 | 
						|
	sub eax, 4
 | 
						|
	mov [ebx], eax
 | 
						|
	POPDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "does>", F_IMMED, WORD_DOES, WORD_CALL_COMMA
 | 
						|
	call WORD_LIT_COMMA
 | 
						|
	LOADTOS [var_WORD_DP]
 | 
						|
	add ebx, 10
 | 
						|
	call WORD_COMMA
 | 
						|
	LOADTOS WORD_DODOES
 | 
						|
	call WORD_COMPILE_COMMA
 | 
						|
	LOADTOS 0
 | 
						|
	mov bl, [does_l1]
 | 
						|
	call WORD_CHAR_COMMA
 | 
						|
does_l1:
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "postpone", F_IMMED, WORD_POSTPONE, WORD_CALL_COMMA
 | 
						|
	call WORD_PARSENAME
 | 
						|
	call WORD_FIND_DICT
 | 
						|
	mov dl, [ebx + H_NSIZE]
 | 
						|
	call WORD_TCFA
 | 
						|
	and edx, F_IMMED
 | 
						|
	if z
 | 
						|
		call WORD_LIT_COMMA
 | 
						|
		call WORD_COMMA
 | 
						|
		LOADTOS WORD_COMPILE_COMMA
 | 
						|
	endif
 | 
						|
	jmp WORD_COMPILE_COMMA
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "call,", 0, WORD_CALL_COMMA, WORD_CALL_COMMA
 | 
						|
	mov edi, [var_WORD_DP]
 | 
						|
	mov [lastcall], edi	; record last location of last call
 | 
						|
	mov esi, i_call
 | 
						|
	movsb
 | 
						|
	mov eax, ebx
 | 
						|
	sub eax, 4
 | 
						|
	sub eax, edi
 | 
						|
	stosd
 | 
						|
	mov [var_WORD_DP], edi
 | 
						|
	POPDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "inline,", 0, WORD_INLINE_COMMA, WORD_CALL_COMMA
 | 
						|
	mov ecx, [ebx + XT_LENGTH]
 | 
						|
	dec ecx					; actual code length minus ret
 | 
						|
	mov esi, ebx
 | 
						|
	mov edi, [var_WORD_DP]
 | 
						|
	rep movsb				; inline copy the code
 | 
						|
	mov [var_WORD_DP], edi	; update DP
 | 
						|
	POPDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "compile,", 0, WORD_COMPILE_COMMA, WORD_INLINE_COMMA
 | 
						|
	call [ebx + XT_COMPILE]
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword ";", F_IMMED, WORD_SEMICOLON, WORD_CALL_COMMA
 | 
						|
	LOADTOS WORD_EXIT
 | 
						|
i_call:
 | 
						|
	call strict near WORD_COMPILE_COMMA
 | 
						|
	call WORD_LATEST
 | 
						|
	call WORD_FETCH
 | 
						|
	call WORD_HIDDEN			; toggle hidden flag -- unhide the word (see below for definition).
 | 
						|
	call WORD_LBRAC				; go back to IMMEDIATE mode.
 | 
						|
	mov edx, ebx
 | 
						|
	mov ebx, [var_WORD_LATEST]
 | 
						|
	call WORD_TCFA
 | 
						|
	mov ecx, [var_WORD_DP]
 | 
						|
	sub ecx, ebx
 | 
						|
	mov [ebx + XT_LENGTH], ecx	; set code size of word
 | 
						|
	mov ebx, edx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "immediate", 0, WORD_IMMEDIATE, WORD_CALL_COMMA
 | 
						|
	mov edi, [var_WORD_LATEST]	; LATEST word.
 | 
						|
	add edi, H_NSIZE			; Point to name/flags byte.
 | 
						|
	xor byte [edi], F_IMMED		; Toggle the IMMED bit.
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "hidden", 0, WORD_HIDDEN, WORD_CALL_COMMA
 | 
						|
	add ebx, H_NSIZE			; Point to name/flags byte.
 | 
						|
	xor byte [ebx], F_HIDDEN	; Toggle the HIDDEN bit.
 | 
						|
	POPDSP ebx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "[", F_IMMED, WORD_LBRAC, WORD_CALL_COMMA
 | 
						|
	mov long [var_WORD_STATE], 0	; Set STATE to 0.
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "]", 0, WORD_RBRAC, WORD_CALL_COMMA
 | 
						|
	mov long [var_WORD_STATE], 1	; Set STATE to 1.
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; source buffer words
 | 
						|
;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "source", 0, WORD_SOURCE, WORD_CALL_COMMA
 | 
						|
	call WORD_INHASH
 | 
						|
	call WORD_FETCH2
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "refill", 0, WORD_REFILL, WORD_CALL_COMMA
 | 
						|
	LOADTOS tib_buffer
 | 
						|
	call WORD_LINESIZE	; ( tib len )
 | 
						|
	call WORD_OVER
 | 
						|
	call WORD_SWAP		; ( tib tib len )
 | 
						|
	call WORD_ACCEPT	; read line into TIB
 | 
						|
	call WORD_DUP2
 | 
						|
	call WORD_TABSTOSPACES
 | 
						|
	call WORD_INHASH
 | 
						|
	call WORD_STORE2	; set as current WORD_SOURCE
 | 
						|
	LOADTOS 0
 | 
						|
	call WORD_TOIN
 | 
						|
	call WORD_STORE		; set to start of buffer
 | 
						|
	LOADTOS -1
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "isspace?", 0, WORD_ISSPACE, WORD_CALL_COMMA
 | 
						|
	LOADTOS ' '
 | 
						|
	call WORD_ULTEQ
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "isnotspace?", 0, WORD_ISNOTSPACE, WORD_CALL_COMMA
 | 
						|
	call WORD_ISSPACE
 | 
						|
	call WORD_ZEQ
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "xt-skip", 0, WORD_XTSKIP, WORD_CALL_COMMA
 | 
						|
	TORSP
 | 
						|
xtskip_l1:
 | 
						|
	test ebx, ebx
 | 
						|
	jz xtskip_l3
 | 
						|
	call WORD_OVER
 | 
						|
	call WORD_FETCHBYTE
 | 
						|
	FETCHRSP
 | 
						|
	call WORD_EXECUTE
 | 
						|
	test ebx, ebx
 | 
						|
	jz xtskip_l2
 | 
						|
	mov ebx, 1
 | 
						|
	call WORD_SSTRING
 | 
						|
	jmp xtskip_l1
 | 
						|
xtskip_l2:
 | 
						|
	call WORD_DROP
 | 
						|
xtskip_l3:
 | 
						|
	ADDRSP 4
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; input parseing words
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "parse-name", 0, WORD_PARSENAME, WORD_CALL_COMMA
 | 
						|
	call WORD_SOURCE
 | 
						|
	call WORD_TOIN
 | 
						|
	call WORD_FETCH
 | 
						|
	call WORD_SSTRING
 | 
						|
	LOADTOS WORD_ISSPACE
 | 
						|
	call WORD_XTSKIP
 | 
						|
	call WORD_OVER
 | 
						|
	TORSP
 | 
						|
	LOADTOS WORD_ISNOTSPACE
 | 
						|
	call WORD_XTSKIP
 | 
						|
	call WORD_DUP2
 | 
						|
	LOADTOS 1
 | 
						|
	call WORD_MIN
 | 
						|
	call WORD_ADD
 | 
						|
	call WORD_SOURCE
 | 
						|
	call WORD_DROP
 | 
						|
	call WORD_SUB
 | 
						|
	call WORD_TOIN
 | 
						|
	call WORD_STORE
 | 
						|
	call WORD_DROP
 | 
						|
	FROMRSP
 | 
						|
	call WORD_TUCK
 | 
						|
	call WORD_SUB
 | 
						|
; code to print out "P <word> CR"
 | 
						|
;LOADTOS 80
 | 
						|
;call WORD_EMIT
 | 
						|
;LOADTOS 32
 | 
						|
;call WORD_EMIT
 | 
						|
;call WORD_DUP2
 | 
						|
;call WORD_TYPE
 | 
						|
;LOADTOS 10
 | 
						|
;call WORD_EMIT
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "word-name", 0, WORD_WORDNAME, WORD_CALL_COMMA
 | 
						|
	call WORD_PARSENAME		; ( start len )
 | 
						|
	LOADTOS word_buf		; ( string size buf )
 | 
						|
	call WORD_DUP2			; ( string size buf size buf )
 | 
						|
	call WORD_STOREBYTE		; ( string size buf )
 | 
						|
	call WORD_INCR			; ( string size buf+1 )
 | 
						|
	call WORD_SWAP			; ( string buf+1 size )
 | 
						|
	call WORD_CMOVE
 | 
						|
	LOADTOS word_buf		; ( cstring )
 | 
						|
; debug code to print out "N <word> CR"
 | 
						|
;LOADTOS 78
 | 
						|
;call WORD_EMIT
 | 
						|
;LOADTOS 32
 | 
						|
;call WORD_EMIT
 | 
						|
;call WORD_DUP2
 | 
						|
;call WORD_TYPE
 | 
						|
;LOADTOS 10
 | 
						|
;call WORD_EMIT
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "interp-name", 0, WORD_INTERPNAME, WORD_CALL_COMMA
 | 
						|
	call WORD_PARSENAME			; ( start len )
 | 
						|
	LOADTOS intep_name_buf		; ( string size buf )
 | 
						|
	call WORD_DUP2				; ( string size buf size buf )
 | 
						|
	call WORD_STOREBYTE			; ( string size buf )
 | 
						|
	call WORD_INCR				; ( string size buf+1 )
 | 
						|
	call WORD_SWAP				; ( string buf+1 size )
 | 
						|
	call WORD_CMOVE
 | 
						|
	LOADTOS intep_name_buf		;( cstring )
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "interpret", 0, WORD_INTERPRET, WORD_CALL_COMMA
 | 
						|
	loopstart
 | 
						|
		call WORD_INTERPNAME
 | 
						|
		mov al, [ebx]
 | 
						|
		test al, al
 | 
						|
		breakif z
 | 
						|
		; debug code to print out "I <word> CR"
 | 
						|
		;LOADTOS 73
 | 
						|
		;call WORD_EMIT
 | 
						|
		;LOADTOS 32
 | 
						|
		;call WORD_EMIT
 | 
						|
		;call WORD_DUP
 | 
						|
		;call WORD_COUNT
 | 
						|
		;call WORD_TYPE
 | 
						|
		;LOADTOS 10
 | 
						|
		;call WORD_EMIT
 | 
						|
		call WORD_INTERP
 | 
						|
	loopend
 | 
						|
	call WORD_DROP
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword "interp", 0, WORD_INTERP, WORD_CALL_COMMA
 | 
						|
	call WORD_FIND				; ( cstring 0 | xt 1 | xt | -1 )
 | 
						|
	mov eax, ebx
 | 
						|
	POPDSP ebx
 | 
						|
	test eax, eax
 | 
						|
	jz tryasnumber
 | 
						|
	jle nonimediate
 | 
						|
executeword:
 | 
						|
	mov eax, ebx
 | 
						|
	POPDSP ebx
 | 
						|
	jmp eax
 | 
						|
nonimediate:
 | 
						|
	mov eax, [var_WORD_STATE]
 | 
						|
	test eax, eax				; are we in imedeate mode ?
 | 
						|
	jz executeword
 | 
						|
	jmp WORD_COMPILE_COMMA		; compile xt
 | 
						|
tryasnumber:
 | 
						|
	call WORD_COUNT				; ( adr len )
 | 
						|
	LOADTOS 0
 | 
						|
	LOADTOS 0
 | 
						|
	call WORD_SWAP2				; ( 0d addr len )
 | 
						|
	call WORD_TOSNUMBER			; ( d addr len )
 | 
						|
	test ebx, ebx
 | 
						|
	jnz parseproblem
 | 
						|
	call WORD_DROP2
 | 
						|
	call WORD_DROP				; ( num )
 | 
						|
	mov eax, [var_WORD_STATE]
 | 
						|
	test eax, eax
 | 
						|
	if nz
 | 
						|
		call WORD_LIT_COMMA		; compile LIT
 | 
						|
		call WORD_COMMA			; compile value
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
parseproblem:
 | 
						|
	LOADTOS errmsg
 | 
						|
	LOADTOS errmsgend - errmsg
 | 
						|
	LOADTOS 2
 | 
						|
	call WORD_TYPE_FD
 | 
						|
	LOADTOS errmsgnl
 | 
						|
	LOADTOS 1
 | 
						|
	LOADTOS 2
 | 
						|
	call WORD_TYPE_FD
 | 
						|
	LOADTOS tib_buffer
 | 
						|
	LOADTOS [var_WORD_TOIN]
 | 
						|
	LOADTOS 2
 | 
						|
	call WORD_TYPE_FD
 | 
						|
	LOADTOS errmsgnl
 | 
						|
	LOADTOS 1
 | 
						|
	LOADTOS 2
 | 
						|
	call WORD_TYPE_FD
 | 
						|
	call WORD_DROP2
 | 
						|
	call WORD_DROP2
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword ">number", 0, WORD_TONUMBER, WORD_CALL_COMMA
 | 
						|
	call WORD_OVER
 | 
						|
	call WORD_ADD
 | 
						|
	call WORD_SWAP			; ( ud end cur )
 | 
						|
tonumber_l1:
 | 
						|
	PICKDSP eax, 0
 | 
						|
	cmp ebx, eax
 | 
						|
	jz near tonumber_l4
 | 
						|
	call WORD_DUP
 | 
						|
	call WORD_FETCHBYTE		; ( ud end cur char )
 | 
						|
	to_lower ebx
 | 
						|
	sub ebx, byte '0'
 | 
						|
	jb tonumber_l3			; < '0'?
 | 
						|
	cmp ebx, byte 10
 | 
						|
	jb tonumber_l2			; <= '9' ?
 | 
						|
	sub ebx, byte 'a' - '0'
 | 
						|
	jb tonumber_l3			; < 'a' ?
 | 
						|
	add ebx, byte 10
 | 
						|
tonumber_l2:
 | 
						|
	cmp ebx, [var_WORD_BASE]
 | 
						|
	jge tonumber_l3			; >= WORD_BASE ?
 | 
						|
	TORSP
 | 
						|
	call WORD_SWAP2			; ( end cur ud )
 | 
						|
	LOADTOS [var_WORD_BASE]
 | 
						|
	call WORD_DMULSTAR
 | 
						|
	FROMRSP
 | 
						|
	call WORD_MPLUS			; ( end cur ud' )
 | 
						|
	call WORD_SWAP2
 | 
						|
	call WORD_INCR			; ( ud' end cur' )
 | 
						|
	jmp tonumber_l1
 | 
						|
tonumber_l3:
 | 
						|
	call WORD_DROP
 | 
						|
tonumber_l4:
 | 
						|
	call WORD_SWAP
 | 
						|
	call WORD_OVER
 | 
						|
	call WORD_SUB			; ( ud' c-addr u2 )
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
	defword ">snumber", 0, WORD_TOSNUMBER, WORD_CALL_COMMA
 | 
						|
	test ebx, ebx
 | 
						|
	if nz
 | 
						|
		PICKDSP eax, 0
 | 
						|
		mov cl, [eax]
 | 
						|
		cmp cl, '-'
 | 
						|
		jnz WORD_TONUMBER	; not '-'
 | 
						|
		inc eax
 | 
						|
		PUTDSP eax, 0
 | 
						|
		dec ebx
 | 
						|
		call WORD_TONUMBER
 | 
						|
		call WORD_SWAP2
 | 
						|
		call WORD_DNEGATE
 | 
						|
		call WORD_SWAP2
 | 
						|
	endif
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;
 | 
						|
; tick word
 | 
						|
;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "ticks", 0, WORD_TICKS, WORD_CALL_COMMA
 | 
						|
	sub ebp, byte 8
 | 
						|
	rdtsc
 | 
						|
	mov [byte ebp -4], ebx
 | 
						|
	mov [ebp], eax
 | 
						|
	mov ebx, edx
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;
 | 
						|
; test word
 | 
						|
;;;;;;;;;;;
 | 
						|
 | 
						|
	defword "test", 0, WORD_TEST, WORD_CALL_COMMA
 | 
						|
	ret
 | 
						|
	defword_end
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;
 | 
						|
; read/write data
 | 
						|
;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	align 4
 | 
						|
syscallret:
 | 
						|
	; return address saved by syscall
 | 
						|
	dd 0
 | 
						|
lastcall:
 | 
						|
	; last call layed down by compiler
 | 
						|
	dd 0
 | 
						|
 | 
						|
tib_buffer:
 | 
						|
	; keyboard input buffer
 | 
						|
	times MAX_LINE_SIZE db 0
 | 
						|
word_buf:
 | 
						|
	; static buffer where WORD returns. Subsequent calls
 | 
						|
	; overwrite this buffer.
 | 
						|
	times MAX_LINE_SIZE db 0
 | 
						|
intep_name_buf:
 | 
						|
	; static buffer where INTERPNAME returns. Subsequent calls
 | 
						|
	; overwrite this buffer.
 | 
						|
	times MAX_LINE_SIZE db 0
 | 
						|
emit_scratch:
 | 
						|
	; scratch used by EMIT
 | 
						|
	db 0
 | 
						|
errmsg:
 | 
						|
	db "PARSE ERROR:"
 | 
						|
errmsgend:
 | 
						|
errmsgnl:
 | 
						|
	db 10
 | 
						|
bootfile:
 | 
						|
	db "forth.f"
 | 
						|
	db 0
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; dictionary hash table (64)
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	align 4
 | 
						|
hash_buckets:
 | 
						|
	dd 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 | 
						|
	dd 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 | 
						|
	dd 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 | 
						|
	dd 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; addresses of all built in dictionary words.
 | 
						|
; this ends up as part of the user space after booting !
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	align 4
 | 
						|
dictionary_start:
 | 
						|
	dd dic_WORD_ABS
 | 
						|
	dd dic_WORD_ACCEPT
 | 
						|
	dd dic_WORD_ADD
 | 
						|
	dd dic_WORD_ADDBYTE
 | 
						|
	dd dic_WORD_ADDSTORE
 | 
						|
	dd dic_WORD_ALIGNDP
 | 
						|
	dd dic_WORD_AND
 | 
						|
	dd dic_WORD_BASE
 | 
						|
	dd dic_WORD_BLANK
 | 
						|
	dd dic_WORD_BLK
 | 
						|
	dd dic_WORD_BRANCH
 | 
						|
	dd dic_WORD_BUCKET
 | 
						|
	dd dic_WORD_CALL_COMMA
 | 
						|
	dd dic_WORD_CHARBUF
 | 
						|
	dd dic_WORD_CHAR_COMMA
 | 
						|
	dd dic_WORD_CLITS
 | 
						|
	dd dic_WORD_CMOVE
 | 
						|
	dd dic_WORD_CMOVEB
 | 
						|
	dd dic_WORD_COLON
 | 
						|
	dd dic_WORD_COMMA
 | 
						|
	dd dic_WORD_COMPARE
 | 
						|
	dd dic_WORD_COMPAREI
 | 
						|
	dd dic_WORD_COMPILE_COMMA
 | 
						|
	dd dic_WORD_COUNT
 | 
						|
	dd dic_WORD_CREATE
 | 
						|
	dd dic_WORD_D2SLASH
 | 
						|
	dd dic_WORD_D2STAR
 | 
						|
	dd dic_WORD_DABS
 | 
						|
	dd dic_WORD_DECR
 | 
						|
	dd dic_WORD_DECR2
 | 
						|
	dd dic_WORD_DECR4
 | 
						|
	dd dic_WORD_DEQ
 | 
						|
	dd dic_WORD_DIV
 | 
						|
	dd dic_WORD_DIVMOD
 | 
						|
	dd dic_WORD_DLT
 | 
						|
	dd dic_WORD_DMAX
 | 
						|
	dd dic_WORD_DMIN
 | 
						|
	dd dic_WORD_DMINUS
 | 
						|
	dd dic_WORD_DMULSTAR
 | 
						|
	dd dic_WORD_DNEGATE
 | 
						|
	dd dic_WORD_DNEQ
 | 
						|
	dd dic_WORD_DODOES
 | 
						|
	dd dic_WORD_DOES
 | 
						|
	dd dic_WORD_DP
 | 
						|
	dd dic_WORD_DPLUS
 | 
						|
	dd dic_WORD_DROP
 | 
						|
	dd dic_WORD_DROP2
 | 
						|
	dd dic_WORD_DSPFETCH
 | 
						|
	dd dic_WORD_DSPSTORE
 | 
						|
	dd dic_WORD_DTOS
 | 
						|
	dd dic_WORD_DULT
 | 
						|
	dd dic_WORD_DUP
 | 
						|
	dd dic_WORD_DUP2
 | 
						|
	dd dic_WORD_DZEQ
 | 
						|
	dd dic_WORD_DZLT
 | 
						|
	dd dic_WORD_DZNEQ
 | 
						|
	dd dic_WORD_EMIT
 | 
						|
	dd dic_WORD_EQ
 | 
						|
	dd dic_WORD_ERASE
 | 
						|
	dd dic_WORD_EXECUTE
 | 
						|
	dd dic_WORD_EXIT
 | 
						|
	dd dic_WORD_FETCH
 | 
						|
	dd dic_WORD_FETCH2
 | 
						|
	dd dic_WORD_FETCHBYTE
 | 
						|
	dd dic_WORD_FETCHSHORT
 | 
						|
	dd dic_WORD_FILL
 | 
						|
	dd dic_WORD_FIND
 | 
						|
	dd dic_WORD_FIND_DICT
 | 
						|
	dd dic_WORD_FMDIVMOD
 | 
						|
	dd dic_WORD_FROMR
 | 
						|
	dd dic_WORD_FROMR2
 | 
						|
	dd dic_WORD_GT
 | 
						|
	dd dic_WORD_GTEQ
 | 
						|
	dd dic_WORD_HEADER_COMMA
 | 
						|
	dd dic_WORD_HIDDEN
 | 
						|
	dd dic_WORD_IMMEDIATE
 | 
						|
	dd dic_WORD_INCR
 | 
						|
	dd dic_WORD_INCR2
 | 
						|
	dd dic_WORD_INCR4
 | 
						|
	dd dic_WORD_INHASH
 | 
						|
	dd dic_WORD_INLINE_COMMA
 | 
						|
	dd dic_WORD_INTERP
 | 
						|
	dd dic_WORD_INTERPNAME
 | 
						|
	dd dic_WORD_INTERPRET
 | 
						|
	dd dic_WORD_INVERT
 | 
						|
	dd dic_WORD_ISNOTSPACE
 | 
						|
	dd dic_WORD_ISSPACE
 | 
						|
	dd dic_WORD_KEY
 | 
						|
	dd dic_WORD_LATEST
 | 
						|
	dd dic_WORD_LBRAC
 | 
						|
	dd dic_WORD_LINESIZE
 | 
						|
	dd dic_WORD_LIT_COMMA
 | 
						|
	dd dic_WORD_LSHIFT
 | 
						|
	dd dic_WORD_LSYSCALL
 | 
						|
	dd dic_WORD_LT
 | 
						|
	dd dic_WORD_LTEQ
 | 
						|
	dd dic_WORD_MAX
 | 
						|
	dd dic_WORD_MIN
 | 
						|
	dd dic_WORD_MMINUS
 | 
						|
	dd dic_WORD_MOD
 | 
						|
	dd dic_WORD_MOVE
 | 
						|
	dd dic_WORD_MPLUS
 | 
						|
	dd dic_WORD_MSLASH
 | 
						|
	dd dic_WORD_MULDIV
 | 
						|
	dd dic_WORD_MULL
 | 
						|
	dd dic_WORD_MULSTAR
 | 
						|
	dd dic_WORD_NE
 | 
						|
	dd dic_WORD_NEGATE
 | 
						|
	dd dic_WORD_NFROMR
 | 
						|
	dd dic_WORD_NIP
 | 
						|
	dd dic_WORD_NIP2
 | 
						|
	dd dic_WORD_NQDUP
 | 
						|
	dd dic_WORD_NROT
 | 
						|
	dd dic_WORD_NTOR
 | 
						|
	dd dic_WORD_OR
 | 
						|
	dd dic_WORD_OVER
 | 
						|
	dd dic_WORD_OVER2
 | 
						|
	dd dic_WORD_O_APPEND
 | 
						|
	dd dic_WORD_O_CREAT
 | 
						|
	dd dic_WORD_O_EXCL
 | 
						|
	dd dic_WORD_O_NONBLOCK
 | 
						|
	dd dic_WORD_O_RDONLY
 | 
						|
	dd dic_WORD_O_RDWR
 | 
						|
	dd dic_WORD_O_TRUNC
 | 
						|
	dd dic_WORD_O_WRONLY
 | 
						|
	dd dic_WORD_PARSENAME
 | 
						|
	dd dic_WORD_PICK
 | 
						|
	dd dic_WORD_POSTPONE
 | 
						|
	dd dic_WORD_QDUP
 | 
						|
	dd dic_WORD_RBRAC
 | 
						|
	dd dic_WORD_RDROP
 | 
						|
	dd dic_WORD_RDROP2
 | 
						|
	dd dic_WORD_READCHAR
 | 
						|
	dd dic_WORD_READLINE
 | 
						|
	dd dic_WORD_REFILL
 | 
						|
	dd dic_WORD_RFETCH
 | 
						|
	dd dic_WORD_RFETCH2
 | 
						|
	dd dic_WORD_ROT
 | 
						|
	dd dic_WORD_ROT2
 | 
						|
	dd dic_WORD_RSHIFT
 | 
						|
	dd dic_WORD_RSPFETCH
 | 
						|
	dd dic_WORD_RSPSTORE
 | 
						|
	dd dic_WORD_RSTORE
 | 
						|
	dd dic_WORD_RZ
 | 
						|
	dd dic_WORD_SEMICOLON
 | 
						|
	dd dic_WORD_SLITS
 | 
						|
	dd dic_WORD_SMDIVREM
 | 
						|
	dd dic_WORD_SOURCE
 | 
						|
	dd dic_WORD_SOURCEFD
 | 
						|
	dd dic_WORD_SSTRING
 | 
						|
	dd dic_WORD_STARSMOD
 | 
						|
	dd dic_WORD_STATE
 | 
						|
	dd dic_WORD_STOD
 | 
						|
	dd dic_WORD_STORE
 | 
						|
	dd dic_WORD_STORE2
 | 
						|
	dd dic_WORD_STOREBYTE
 | 
						|
	dd dic_WORD_STORESHORT
 | 
						|
	dd dic_WORD_SUB
 | 
						|
	dd dic_WORD_SUBSTORE
 | 
						|
	dd dic_WORD_SWAP
 | 
						|
	dd dic_WORD_SWAP2
 | 
						|
	dd dic_WORD_SYSCALL
 | 
						|
	dd dic_WORD_SYS_CLOSE
 | 
						|
	dd dic_WORD_SYS_EXIT
 | 
						|
	dd dic_WORD_SYS_FSTAT
 | 
						|
	dd dic_WORD_SYS_FSYNC
 | 
						|
	dd dic_WORD_SYS_FTRUNCATE
 | 
						|
	dd dic_WORD_SYS_LSEEK
 | 
						|
	dd dic_WORD_SYS_OPEN
 | 
						|
	dd dic_WORD_SYS_READ
 | 
						|
	dd dic_WORD_SYS_RENAME
 | 
						|
	dd dic_WORD_SYS_STAT
 | 
						|
	dd dic_WORD_SYS_UNLINK
 | 
						|
	dd dic_WORD_SYS_WRITE
 | 
						|
	dd dic_WORD_SZ
 | 
						|
	dd dic_WORD_TABSTOSPACES
 | 
						|
	dd dic_WORD_TCFA
 | 
						|
	dd dic_WORD_TICKS
 | 
						|
	dd dic_WORD_TOIN
 | 
						|
	dd dic_WORD_TONUMBER
 | 
						|
	dd dic_WORD_TOR
 | 
						|
	dd dic_WORD_TOR2
 | 
						|
	dd dic_WORD_TOSNUMBER
 | 
						|
	dd dic_WORD_TRAILING
 | 
						|
	dd dic_WORD_TUCK
 | 
						|
	dd dic_WORD_TUCK2
 | 
						|
	dd dic_WORD_TWODIV
 | 
						|
	dd dic_WORD_TWOMUL
 | 
						|
	dd dic_WORD_TYPE
 | 
						|
	dd dic_WORD_TYPE_FD
 | 
						|
	dd dic_WORD_UDIVMOD
 | 
						|
	dd dic_WORD_UGT
 | 
						|
	dd dic_WORD_UGTEQ
 | 
						|
	dd dic_WORD_ULT
 | 
						|
	dd dic_WORD_ULTEQ
 | 
						|
	dd dic_WORD_UMDIVMOD
 | 
						|
	dd dic_WORD_UMULSTAR
 | 
						|
	dd dic_WORD_UNUSED
 | 
						|
	dd dic_WORD_VERSION
 | 
						|
	dd dic_WORD_WORDBUF
 | 
						|
	dd dic_WORD_WORDNAME
 | 
						|
	dd dic_WORD_XOR
 | 
						|
	dd dic_WORD_XTSKIP
 | 
						|
	dd dic_WORD_ZBRANCH
 | 
						|
	dd dic_WORD_ZEQ
 | 
						|
	dd dic_WORD_ZGT
 | 
						|
	dd dic_WORD_ZGTEQ
 | 
						|
	dd dic_WORD_ZLT
 | 
						|
	dd dic_WORD_ZLTEQ
 | 
						|
	dd dic_WORD_ZNE
 | 
						|
	dd dic_WORD__F_HIDDEN
 | 
						|
	dd dic_WORD__F_IMMED
 | 
						|
	dd dic_WORD__F_LENMASK
 | 
						|
	dd dic_WORD__H_NAME
 | 
						|
	dd dic_WORD__H_NSIZE
 | 
						|
	dd dic_WORD__XT_BODY
 | 
						|
	dd dic_WORD__XT_COMPILE
 | 
						|
	dd dic_WORD__XT_LENGTH
 | 
						|
	dd dic_WORD__XT_SIZE
 | 
						|
	dd dic_WORD_TEST
 | 
						|
dictionary_end:
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
; room for user dictionary
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
	times USER_DEFS_SIZE db 0
 | 
						|
forth_end:
 |