eForth1
v2.6
|
eForth Assembler module More...
#include "eforth_asm.h"
Macros | |
#define | WORDS_ROW_WIDTH 0x44 /** WORDS row width control */ |
Functions | |
int | assemble (U8 *rom) |
void | _dump_rom (U8 *rom, int len) |
Variables | |
eForth Assembler module variables | |
IU | PC |
assembler program counter More... | |
U8 | R |
assembler return stack index More... | |
U8 * | _byte |
assembler byte array (heap) More... | |
IU | _link |
link to previous word More... | |
Compiled Address for Branching | |
IU | DOTQP |
addr of output ops, used by _dotq, _strq, _abortq More... | |
eForth Assembler module
Forth Macro Assembler Note: TODO: adding Leo Brodie's words
#define WORDS_ROW_WIDTH 0x44 /** WORDS row width control */ |
int assemble | ( | U8 * | rom | ) |
eForth Macro Assembler
ROM starting address
< reserved for COLD boot vector
Kernel dictionary (primitive words)
aka doLIST
( u ul uh – f ) check 3rd item within [ul uh)
( udl udh u – ur uq ) unsigned double divided by a single
( u1 u2 – ud ) unsigned double = multiply unsigned singles
( n1 n2 – d ) double = single * single
( n1 n2 – sum c ) add two numbers and carry flag
( n1 n2 n – r q ) multiply n1 n2 div/mod by a single
( n1 n2 – r q ) single devide
( n1 n2 n3 – q ) multiply n1 n2 divide by n3 return quotient
( n – dl dh )
( dl dh – n )
( dl dh – dl' dh' )
( d1l d1h d2l d2h – drl drh dql dqh )
extended words
base of data stack (fixed instead of user var)
address of stack pointer
(TODO: add J)
( f – ) enable/disable debug tracing
( – ) save user variables and dictionary to EEPROM
( – ) restore user variables and dictionary from EERPROM
( n – ) call a C-function vector
Kernel constants
- 'TIB console input buffer pointer
- BASE current radix for numeric ops
- CP, top of dictionary, same as HERE
- CONTEXT name field of last word
- LAST, same as CONTEXT
- 'MODE ('TEVAL - interpreter or compiler)
- ABORT exception rescue handler (QUIT)
- HLD char pointer to output buffer
- SPAN number of character accepted
- >IN interpreter pointer to next char
- #TIB number of character received in TIB
- tmp storage (alternative to return stack)
Console Input and Common words
top of dictionary
use tail of TIB for output
Number Conversions and formatting
( dl dh n – dql dqh u )
handle hex number
handle base > 10
TODO: add >NUMBER
leading with $ (i.e. 0x24)
a FOR..WHILE..NEXT..ELSE..THEN construct =~ for {..break..}
if digit, xBASE, else break to ELSE
whether negative number
Console Output
out-of-range put '_' instead
LF i.e.
actually
Note: DOTQP export to _dotq
( d n – ) fixed width
( u n – ) unsigned fixed size
( u – ) unsigned
( d – ) print, extra space
memory query
TODO: add PAGE
Parsing
( addr len delim – ) delimiter kept tmp, addr in R
if (len) { –len; if (delim==" ") {...} }
a FOR..WHILE..NEXT..THEN construct =~ for {..break..}
for (len)
break to THEN if is char, or next char
no break, (R>, DROP to rm loop counter)
populate A0, i.e. break comes here, rm counter
advance until next space found
a FOR..WHILE..NEXT..ELSE..THEN construct =~ DO..LEAVE..+LOOP
if (char <= space) break to ELSE
no break, if counter < limit loop back to FOR
R>, DROP to rm loop counter
put token length on stack
( b u a – a )
( c – b u )
( – a; <string>) put token at HERE
( c – a; <string)
Dictionary serach
( nfa – cfa )
( a1 a2 n - a1 a2 f ) compare a1, a2 byte-by-byte
*a1++
*a2++
CASE_SENSITIVE
pop off loop counter and pointers
SAME!
TODO: add COMPARE
( a va – cfa nfa, a F ) keep length in tmp
fetch 1st cell
0000 = end of dic
compare 2-byte (uppercased)
CASE_SENSITIVE
miss, try next word
-1, since 1st byte has been compared
compare strings if larger than 2 bytes
get thread field to previous word
word found, get name field
Terminal Input
echo and store new char to TIB
check <CR><LF>
check <TAB>
check BLANK
accquire token from console
loop through input stream
store new char into TIB
check if done
keep token length in #TIB
Text Interpreter
QUERY/TIB/ACCEPT - start the interpreter loop <-------<------. TOKEN/PARSE - get a space delimited word . EXECUTE - attempt to look up that word in the dictionary . NAME?/find - was the word found? ^ |-Yes: | | $INTERPRET - are we in compile mode? | | |-Yes: ^ | | \-Is the Word an Immediate word? | | | |-Yes: | | | | \- EXECUTE Execute the word -------------------->. | | | | | | | | \- if (NAME?) EXECU else NUMBQ ---------------->. | | \-No: | | | \-Compile the word into the dictionary --------->. | \-No: | | \- EXECUTE Execute the word ----->------------------->. \-No: ^ NUMBER? - Can the word be treated as a number? | |-Yes: | | \-Are we in compile mode? | | |-Yes: | | | | | | | \-Compile a literal into the dictionary >--------->. | | | | \-No: | | | | | \-Push the number to the variable stack >--------->. \-No: . \-An Error has occurred, prIU out an error message ->
load ABORT vector
@EXECUTE
TODO: add ?STACK
scan dictionary for word
check for compile only word
INTER0 of Dr Ting's
word name not found, check if it is a number
dump stack and ok prompt
fetch token length
fetch operation mode ($INTERPRET or $COMPILE)
execute according to mode
clear TIB, interpreter mode
main query-eval loop
Colon Compiler
store a byte
store a word
create a literal
name found?
is immediate?
execute
a primitive?
XX08 <= this might break
append just the opcode
append colon word address with flag
a number?
append as a literal
add new name field which is already build by PACK$
switch into compiler-mode
TODO: add [']
add word address to dictionary
Debugging Tools
( pfa – nfa )
save BASE, make HEX
get row count
dump one row
:
low-nibble
high-nibble
restore BASE
tmp keeps width
get name length
add to tmp
get LFA
check row width
Optional: Takes ~300 bytes ROM space
display address with colon delimiter ( a – )
display opcode at given address ( a0 op – a1 )
check primitive flag?
colon word - show name
."| or $"| (string)"
a literal?
show the number
(var)v
show jump target
(jump target)j
or a qbran
show jump target
(jump target)?
a bran or donext?
show jump target
(jump target)n
DOES>
(var)*
(does> target)j
skip to defining word
show other opcode#
opcode -> name ( a op – a+1 )
0000 = end of dic
primitive words?
same as our opcode?
print name, done!
link to prev word
?(unknown opcode)
word address
loop until EXIT
disasmble opcode
semi colon
ENABLE_SEE
Control Structures
- BEGIN...AGAIN, BEGIN... f UNTIL, BEGIN...(once)...f WHILE...(loop)...REPEAT
- f IF...THEN, f IF...ELSE...THEN
- n FOR...NEXT, n FOR...(first)... f AFT...(2nd,...)...THEN...(every)...NEXT
TODO: add DO...LOOP, +LOOP, LEAVE
String Literals
find quote in TIB (0x22 is " in ASCII)
advance dic pointer
Defining Words - variable, constant, and comments
change runtime behavior to following code
( ra ca ) para on return stack, offset to defining word
TODO: add POSTPONE
Comments
print til hit ) i.e. 0x29
skip til end of line
Lexicon Bits
enable COMPILE-ONLY flag
enable IMMEDIATE flag
Arduino specific opcodes
( – ud ud ) get current clock (in ms)
( n p – ) set pinMode(p, n=1:OUTPUT, n=0: INPUT)
( h l p – ) set map range to pin
( p – n ) digitalRead(p)
( n p – ) digitialWrite(p, n=1 HIGH, n=0 LOW)
( p – n ) read analog value from pin
( n p – ) set duty cycle % (PWM) to pin
( xt n – ) on timer interrupt calls xt every n ms
( xt p – ) on pin change interrupt calls xt
( f – ) enable/disable timer interrupt
( f – ) enable/disable pin change interrupt
Cold Start address (End of dictionary)
name field of last word
reset vectors
enter the main query loop (QUIT)
current pointer
Boot Vector Setup
void _dump_rom | ( | U8 * | rom, |
int | len | ||
) |
create C array dump for ROM