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:
 |