fix DOES> to work as described in the ANS Forth standard

This commit is contained in:
Jesse D. McDonald 2020-10-03 15:25:53 -05:00
parent 3a4e040ec1
commit 60333e365c
2 changed files with 53 additions and 23 deletions

View File

@ -11,6 +11,12 @@
.set DATA_SEGMENT_ALLOC_SIZE,65536 .set DATA_SEGMENT_ALLOC_SIZE,65536
.set F_IMMED,0x80
.set F_HIDDEN,0x40
.set F_LENMASK,0x3f
.set link,0
.macro NEXT .macro NEXT
lodsl lodsl
jmp *(%eax) jmp *(%eax)
@ -58,15 +64,35 @@ DOCOL:
/* (By default the DFA field holds the address of the body of the definition) */ /* (By default the DFA field holds the address of the body of the definition) */
.text .text
.align 4 .align 4
.globl SELF .globl DOSELF
SELF: DOSELF:
pushl 4(%eax) pushl 4(%eax)
NEXT NEXT
.set F_IMMED,0x80 /* The entry point for threaded FORTH words defined with CREATE/DOES> */
.set F_HIDDEN,0x40 /* Push the return address (%esi) on the return stack */
.set F_LENMASK,0x3f /* Load the address of the DOES> code body from the DFA field at %eax+4 */
.set link,0 /* Push the address of the body of the word (not the DFA field) onto the stack */
.text
.align 4
.globl DODOES
DODOES:
/* Save threaded return address */
PUSHRSP %esi
/* Load address of DOES> body from DFA into %esi */
movl 4(%eax),%esi
/* Load name length byte into %eax and mask out flag bits */
xor %ebx,%ebx
movb 12(%eax),%bl
andb $F_LENMASK,%bl
/* Calculate %eax + 13 + %ebx and round up to next cell for address of body */
addl $16,%eax
addl %ebx,%eax
andl $-4,%eax
/* Push body address on the data stack */
push %eax
/* Execute the DOES> code */
NEXT
.macro defname label:req,codeword:req,dataword:req,name="",flags=0 .macro defname label:req,codeword:req,dataword:req,name="",flags=0
.section .rodata .section .rodata
@ -137,7 +163,8 @@ defconst BUFFER,buffer
defconst __BUFFER_SIZE,BUFFER_SIZE,"BUFFER_SIZE" defconst __BUFFER_SIZE,BUFFER_SIZE,"BUFFER_SIZE"
defconst __DOCOL,DOCOL,"DOCOL" defconst __DOCOL,DOCOL,"DOCOL"
defconst __SELF,SELF,"SELF" defconst __DOSELF,DOSELF,"DOSELF"
defconst __DODOES,DODOES,"DODOES"
defconst FALSE,0 defconst FALSE,0
defconst TRUE,-1 defconst TRUE,-1
@ -1104,20 +1131,12 @@ defword QUOTE,"'"
.int WORD,FINDERR,EXIT .int WORD,FINDERR,EXIT
defword CREATE defword CREATE
.int ALIGN,HERE,LIT,SELF,COMMA,LIT,0,COMMA,LATEST,FETCH,COMMA,LIT,0,COMMABYTE .int ALIGN,HERE,LIT,DOSELF,COMMA,LIT,0,COMMA,LATEST,FETCH,COMMA,LIT,0,COMMABYTE
.int WORD,NIP,DUP,ALLOT,ALIGN .int WORD,NIP,DUP,ALLOT,ALIGN
.int OVER,TFLAGS,STOREBYTE .int OVER,TFLAGS,STOREBYTE
.int HERE,OVER,TDFA,STORE .int HERE,OVER,TDFA,STORE
.int LATEST,STORE,EXIT .int LATEST,STORE,EXIT
defword DOES,"DOES>"
.int LATEST,FETCH
.int LIT,DOCOL,OVER,TCFA,STORE
.int ALIGN,HERE,OVER,TDFA,STORE
.int LIT,LIT,COMMA,TBODY,COMMA
.int TRUE,STATE,STORE
.int EXIT
defword COLON,":" defword COLON,":"
.int CREATE .int CREATE
.int LATEST,FETCH .int LATEST,FETCH
@ -1136,13 +1155,24 @@ defword NONAME,":NONAME"
.int TRUE,STATE,STORE .int TRUE,STATE,STORE
.int EXIT .int EXIT
/* ( xt -- ) Clear the F_HIDDEN flag of the word denoted by xt */
defword _UNHIDE_,"(UNHIDE)",F_HIDDEN
.int TFLAGS,DUP,FETCHBYTE,__F_HIDDEN,INVERT,AND,SWAP,STOREBYTE,EXIT
defword SEMI,";",F_IMMED defword SEMI,";",F_IMMED
.int LIT,EXIT,COMMA,LATEST,FETCH,TFLAGS .int LIT,EXIT,COMMA,LATEST,FETCH,_UNHIDE_
.int DUP,FETCHBYTE,DUP,__F_HIDDEN,AND,ZBRANCH,(0f - .) .int FALSE,STATE,STORE,ALIGN,EXIT
.int __F_HIDDEN,SUB,SWAP,STOREBYTE,BRANCH,(1f - .)
0: .int TWODROP /* ( dfa -- ) Set CFA of latest word to DODOES and set DFA field to address on stack */
1: .int FALSE,STATE,STORE defword _DOES_,"(DOES)",F_HIDDEN
.int ALIGN,EXIT .int LATEST,FETCH,LIT,DODOES,OVER,TCFA,STORE,TDFA,STORE,EXIT
/* Append "<addr> (DOES) EXIT" to the current definition */
/* where <addr> is the next address after the "EXIT" as a literal number */
/* Stay in compilation mode for the body of the DOES> clause */
defword DOES,"DOES>",F_IMMED
.int LIT,LIT,COMMA,HERE,LIT,12,ADD,COMMA
.int LIT,_DOES_,COMMA,LIT,EXIT,COMMA,EXIT
defword WORD defword WORD
.int SKIPSPACE,HERE .int SKIPSPACE,HERE

View File

@ -175,7 +175,7 @@
\ Named values defined with VALUE can be modified with TO. \ Named values defined with VALUE can be modified with TO.
\ Execution: ( x "<spaces>name" -- ) \ Execution: ( x "<spaces>name" -- )
\ name execution: ( -- value ) \ name execution: ( -- value )
: VALUE CREATE , POSTPONE DOES> POSTPONE @ POSTPONE ; ; : VALUE CREATE , DOES> @ ;
\ When compiling, append code to store to the data field area of the named value. \ When compiling, append code to store to the data field area of the named value.
\ When interpreting, store to the data field directly. \ When interpreting, store to the data field directly.