| \ throw execute, cfa and NEXT1 out? |
\ throw execute, cfa and NEXT1 out? |
| \ macroize *ip, ip++, *ip++ (pipelining)? |
\ macroize *ip, ip++, *ip++ (pipelining)? |
| |
|
| |
\ Stack caching setup |
| |
|
| |
ifdef(`M4_ENGINE_FAST', `include(cache1.vmg)', `include(cache0.vmg)') |
| |
|
| \ these m4 macros would collide with identifiers |
\ these m4 macros would collide with identifiers |
| undefine(`index') |
undefine(`index') |
| undefine(`shift') |
undefine(`shift') |
| undefine(`symbols') |
undefine(`symbols') |
| |
|
| |
\F 0 [if] |
| |
|
| |
\ run-time routines for non-primitives. They are defined as |
| |
\ primitives, because that simplifies things. |
| |
|
| |
(docol) ( -- R:a_retaddr ) gforth-internal paren_docol |
| |
""run-time routine for colon definitions"" |
| |
#ifdef NO_IP |
| |
a_retaddr = next_code; |
| |
INST_TAIL; |
| |
goto **(Label *)PFA(CFA); |
| |
#else /* !defined(NO_IP) */ |
| |
a_retaddr = (Cell *)IP; |
| |
SET_IP((Xt *)PFA(CFA)); |
| |
#endif /* !defined(NO_IP) */ |
| |
|
| |
(docon) ( -- w ) gforth-internal paren_docon |
| |
""run-time routine for constants"" |
| |
w = *(Cell *)PFA(CFA); |
| |
#ifdef NO_IP |
| |
INST_TAIL; |
| |
goto *next_code; |
| |
#endif /* defined(NO_IP) */ |
| |
|
| |
(dovar) ( -- a_body ) gforth-internal paren_dovar |
| |
""run-time routine for variables and CREATEd words"" |
| |
a_body = PFA(CFA); |
| |
#ifdef NO_IP |
| |
INST_TAIL; |
| |
goto *next_code; |
| |
#endif /* defined(NO_IP) */ |
| |
|
| |
(douser) ( -- a_user ) gforth-internal paren_douser |
| |
""run-time routine for constants"" |
| |
a_user = (Cell *)(up+*(Cell *)PFA(CFA)); |
| |
#ifdef NO_IP |
| |
INST_TAIL; |
| |
goto *next_code; |
| |
#endif /* defined(NO_IP) */ |
| |
|
| |
(dodefer) ( -- ) gforth-internal paren_dodefer |
| |
""run-time routine for deferred words"" |
| |
#ifndef NO_IP |
| |
ip=IP; /* undo any ip updating that may have been performed by NEXT_P0 */ |
| |
#endif /* !defined(NO_IP) */ |
| |
SUPER_END; /* !! probably unnecessary and may lead to measurement errors */ |
| |
EXEC(*(Xt *)PFA(CFA)); |
| |
|
| |
(dofield) ( n1 -- n2 ) gforth-internal paren_field |
| |
""run-time routine for fields"" |
| |
n2 = n1 + *(Cell *)PFA(CFA); |
| |
#ifdef NO_IP |
| |
INST_TAIL; |
| |
goto *next_code; |
| |
#endif /* defined(NO_IP) */ |
| |
|
| |
(dodoes) ( -- a_body R:a_retaddr ) gforth-internal paren_dodoes |
| |
""run-time routine for @code{does>}-defined words"" |
| |
#ifdef NO_IP |
| |
a_retaddr = next_code; |
| |
a_body = PFA(CFA); |
| |
INST_TAIL; |
| |
goto **(Label *)DOES_CODE1(CFA); |
| |
#else /* !defined(NO_IP) */ |
| |
a_retaddr = (Cell *)IP; |
| |
a_body = PFA(CFA); |
| |
SET_IP(DOES_CODE1(CFA)); |
| |
#endif /* !defined(NO_IP) */ |
| |
|
| |
(does-handler) ( -- ) gforth-internal paren_does_handler |
| |
""just a slot to have an encoding for the DOESJUMP, |
| |
which is no longer used anyway (!! eliminate this)"" |
| |
|
| |
\F [endif] |
| |
|
| \g control |
\g control |
| |
|
| noop ( -- ) gforth |
noop ( -- ) gforth |
| call ( #a_callee -- R:a_retaddr ) new |
call ( #a_callee -- R:a_retaddr ) new |
| ""Call callee (a variant of docol with inline argument)."" |
""Call callee (a variant of docol with inline argument)."" |
| #ifdef NO_IP |
#ifdef NO_IP |
| |
assert(0); |
| INST_TAIL; |
INST_TAIL; |
| JUMP(a_callee); |
JUMP(a_callee); |
| #else |
#else |
| #ifndef NO_IP |
#ifndef NO_IP |
| ip=IP; |
ip=IP; |
| #endif |
#endif |
| IF_spTOS(spTOS = sp[0]); |
IF_spTOS(spTOS = sp[0]); /* inst_tail would produce a NEXT_P1 */ |
| SUPER_END; |
SUPER_END; |
| EXEC(xt); |
EXEC(xt); |
| |
|
| #ifndef NO_IP |
#ifndef NO_IP |
| ip=IP; |
ip=IP; |
| #endif |
#endif |
| IF_spTOS(spTOS = sp[0]); |
IF_spTOS(spTOS = sp[0]); /* inst_tail would produce a NEXT_P1 */ |
| SUPER_END; |
SUPER_END; |
| EXEC(*(Xt *)a_addr); |
EXEC(*(Xt *)a_addr); |
| : |
: |
| JUMP(a_target); |
JUMP(a_target); |
| #else |
#else |
| SET_IP((Xt *)a_target); |
SET_IP((Xt *)a_target); |
| |
INST_TAIL; |
| |
NEXT_P2; |
| #endif |
#endif |
| |
SUPER_CONTINUE; /* we do our own control flow, so don't append NEXT etc. */ |
| : |
: |
| r> @ >r ; |
r> @ >r ; |
| |
|
| /* dependent upon two's complement arithmetic */ |
/* dependent upon two's complement arithmetic */ |
| Cell olddiff = n1-nlimit; |
Cell olddiff = n1-nlimit; |
| n2=n1+n; |
n2=n1+n; |
| ,if ((olddiff^(olddiff+n))>=0 /* the limit is not crossed */ |
,if (((olddiff^(olddiff+n)) /* the limit is not crossed */ |
| || (olddiff^n)>=0 /* it is a wrap-around effect */) { |
&(olddiff^n)) /* OR it is a wrap-around effect */ |
| |
>=0) { /* & is used to avoid having two branches for gforth-native */ |
| ,: |
,: |
| r> swap |
r> swap |
| r> r> 2dup - >r |
r> r> 2dup - >r |
| newdiff = -newdiff; |
newdiff = -newdiff; |
| } |
} |
| n2=n1+n; |
n2=n1+n; |
| ,if (diff>=0 || newdiff<0) { |
,if (((~diff)|newdiff)<0) { /* use | to avoid two branches for gforth-native */ |
| ,) |
,) |
| |
|
| \+ |
\+ |
| : |
: |
| rot 2dup swap - >r min swap -text dup |
rot 2dup swap - >r min swap -text dup |
| IF rdrop ELSE drop r> sgn THEN ; |
IF rdrop ELSE drop r> sgn THEN ; |
| |
: -text ( c_addr1 u c_addr2 -- n ) |
| |
swap bounds |
| |
?DO dup c@ I c@ = WHILE 1+ LOOP drop 0 |
| |
ELSE c@ I c@ - unloop THEN sgn ; |
| : sgn ( n -- -1/0/1 ) |
: sgn ( n -- -1/0/1 ) |
| dup 0= IF EXIT THEN 0< 2* 1+ ; |
dup 0= IF EXIT THEN 0< 2* 1+ ; |
| |
|
| ud = (UDCell)u1 * (UDCell)u2; |
ud = (UDCell)u1 * (UDCell)u2; |
| #endif |
#endif |
| : |
: |
| >r >r 0 0 r> r> [ 8 cells ] literal 0 |
0 -rot dup [ 8 cells ] literal - |
| DO |
DO |
| over >r dup >r 0< and d2*+ drop |
dup 0< I' and d2*+ drop |
| r> 2* r> swap |
LOOP ; |
| LOOP 2drop ; |
|
| : d2*+ ( ud n -- ud+n c ) |
: d2*+ ( ud n -- ud+n c ) |
| over MINI |
over MINI |
| and >r >r 2dup d+ swap r> + swap r> ; |
and >r >r 2dup d+ swap r> + swap r> ; |
| |
|
| rshift ( u1 n -- u2 ) core r_shift |
rshift ( u1 n -- u2 ) core r_shift |
| ""Logical shift right by @i{n} bits."" |
""Logical shift right by @i{n} bits."" |
| |
#ifdef BROKEN_SHIFT |
| |
u2 = rshift(u1, n); |
| |
#else |
| u2 = u1>>n; |
u2 = u1>>n; |
| |
#endif |
| : |
: |
| 0 ?DO 2/ MAXI and LOOP ; |
0 ?DO 2/ MAXI and LOOP ; |
| |
|
| lshift ( u1 n -- u2 ) core l_shift |
lshift ( u1 n -- u2 ) core l_shift |
| |
#ifdef BROKEN_SHIFT |
| |
u2 = lshift(u1, n); |
| |
#else |
| u2 = u1<<n; |
u2 = u1<<n; |
| |
#endif |
| : |
: |
| 0 ?DO 2* LOOP ; |
0 ?DO 2* LOOP ; |
| |
|
| : |
: |
| r> r> drop >r ; |
r> r> drop >r ; |
| |
|
| 2>r ( w1 w2 -- R:w1 R:w2 ) core-ext two_to_r |
2>r ( d -- R:d ) core-ext two_to_r |
| : |
: |
| swap r> swap >r swap >r >r ; |
swap r> swap >r swap >r >r ; |
| |
|
| 2r> ( R:w1 R:w2 -- w1 w2 ) core-ext two_r_from |
2r> ( R:d -- d ) core-ext two_r_from |
| : |
: |
| r> r> swap r> swap >r swap ; |
r> r> swap r> swap >r swap ; |
| |
|
| 2r@ ( R:w1 R:w2 -- R:w1 R:w2 w1 w2 ) core-ext two_r_fetch |
2r@ ( R:d -- R:d d ) core-ext two_r_fetch |
| : |
: |
| i' j ; |
i' j ; |
| |
|
| 2rdrop ( R:w1 R:w2 -- ) gforth two_r_drop |
2rdrop ( R:d -- ) gforth two_r_drop |
| : |
: |
| r> r> drop r> drop >r ; |
r> r> drop r> drop >r ; |
| |
|
| |
|
| \g compiler |
\g compiler |
| |
|
| |
\+f83headerstring |
| |
|
| |
(f83find) ( c_addr u f83name1 -- f83name2 ) new paren_f83find |
| |
for (; f83name1 != NULL; f83name1 = (struct F83Name *)(f83name1->next)) |
| |
if ((UCell)F83NAME_COUNT(f83name1)==u && |
| |
memcasecmp(c_addr, f83name1->name, u)== 0 /* or inline? */) |
| |
break; |
| |
f83name2=f83name1; |
| |
: |
| |
BEGIN dup WHILE (find-samelen) dup WHILE |
| |
>r 2dup r@ cell+ char+ capscomp 0= |
| |
IF 2drop r> EXIT THEN |
| |
r> @ |
| |
REPEAT THEN nip nip ; |
| |
: (find-samelen) ( u f83name1 -- u f83name2/0 ) |
| |
BEGIN 2dup cell+ c@ $1F and <> WHILE @ dup 0= UNTIL THEN ; |
| |
: capscomp ( c_addr1 u c_addr2 -- n ) |
| |
swap bounds |
| |
?DO dup c@ I c@ <> |
| |
IF dup c@ toupper I c@ toupper = |
| |
ELSE true THEN WHILE 1+ LOOP drop 0 |
| |
ELSE c@ toupper I c@ toupper - unloop THEN sgn ; |
| |
: sgn ( n -- -1/0/1 ) |
| |
dup 0= IF EXIT THEN 0< 2* 1+ ; |
| |
|
| |
\- |
| |
|
| (listlfind) ( c_addr u longname1 -- longname2 ) new paren_listlfind |
(listlfind) ( c_addr u longname1 -- longname2 ) new paren_listlfind |
| longname2=listlfind(c_addr, u, longname1); |
longname2=listlfind(c_addr, u, longname1); |
| : |
: |
| REPEAT THEN nip nip ; |
REPEAT THEN nip nip ; |
| : (findl-samelen) ( u longname1 -- u longname2/0 ) |
: (findl-samelen) ( u longname1 -- u longname2/0 ) |
| BEGIN 2dup cell+ @ lcount-mask and <> WHILE @ dup 0= UNTIL THEN ; |
BEGIN 2dup cell+ @ lcount-mask and <> WHILE @ dup 0= UNTIL THEN ; |
| |
: capscomp ( c_addr1 u c_addr2 -- n ) |
| |
swap bounds |
| |
?DO dup c@ I c@ <> |
| |
IF dup c@ toupper I c@ toupper = |
| |
ELSE true THEN WHILE 1+ LOOP drop 0 |
| |
ELSE c@ toupper I c@ toupper - unloop THEN sgn ; |
| |
: sgn ( n -- -1/0/1 ) |
| |
dup 0= IF EXIT THEN 0< 2* 1+ ; |
| |
|
| \+hash |
\+hash |
| |
|
| IF 2drop r> rdrop EXIT THEN THEN |
IF 2drop r> rdrop EXIT THEN THEN |
| rdrop r> |
rdrop r> |
| REPEAT nip nip ; |
REPEAT nip nip ; |
| |
: -text ( c_addr1 u c_addr2 -- n ) |
| |
swap bounds |
| |
?DO dup c@ I c@ = WHILE 1+ LOOP drop 0 |
| |
ELSE c@ I c@ - unloop THEN sgn ; |
| |
: sgn ( n -- -1/0/1 ) |
| |
dup 0= IF EXIT THEN 0< 2* 1+ ; |
| |
|
| (hashkey1) ( c_addr u ubits -- ukey ) gforth paren_hashkey1 |
(hashkey1) ( c_addr u ubits -- ukey ) gforth paren_hashkey1 |
| ""ukey is the hash key for the string c_addr u fitting in ubits bits"" |
""ukey is the hash key for the string c_addr u fitting in ubits bits"" |
| |
|
| \+ |
\+ |
| |
|
| |
\+ |
| |
|
| (parse-white) ( c_addr1 u1 -- c_addr2 u2 ) gforth paren_parse_white |
(parse-white) ( c_addr1 u1 -- c_addr2 u2 ) gforth paren_parse_white |
| struct Cellpair r=parse_white(c_addr1, u1); |
struct Cellpair r=parse_white(c_addr1, u1); |
| c_addr2 = (Char *)(r.n1); |
c_addr2 = (Char *)(r.n1); |
| u = strlen(c_addr); |
u = strlen(c_addr); |
| |
|
| strsignal ( n -- c_addr u ) gforth |
strsignal ( n -- c_addr u ) gforth |
| c_addr = strsignal(n); |
c_addr = (Address)strsignal(n); |
| u = strlen(c_addr); |
u = strlen(c_addr); |
| |
|
| call-c ( w -- ) gforth call_c |
call-c ( w -- ) gforth call_c |
| # endif |
# endif |
| #endif |
#endif |
| |
|
| |
wcall ( u -- ) gforth |
| |
IF_fpTOS(fp[0]=fpTOS); |
| |
FP=fp; |
| |
sp=(Cell*)(SYSCALL(Cell*(*)(Cell *, void *))u)(sp, &FP); |
| |
fp=FP; |
| |
IF_spTOS(spTOS=sp[0];) |
| |
IF_fpTOS(fpTOS=fp[0]); |
| |
|
| \+FFCALL |
\+FFCALL |
| |
|
| av-start-void ( c_addr -- ) gforth av_start_void |
av-start-void ( c_addr -- ) gforth av_start_void |
| av_double(alist, r); |
av_double(alist, r); |
| |
|
| av-longlong ( d -- ) gforth av_longlong |
av-longlong ( d -- ) gforth av_longlong |
| |
#ifdef BUGGY_LONG_LONG |
| |
av_longlong(alist, d.lo); |
| |
#else |
| av_longlong(alist, d); |
av_longlong(alist, d); |
| |
#endif |
| |
|
| av-ptr ( c_addr -- ) gforth av_ptr |
av-ptr ( c_addr -- ) gforth av_ptr |
| av_ptr(alist, void*, c_addr); |
av_ptr(alist, void*, c_addr); |
| |
|
| |
av-int-r ( R:w -- ) gforth av_int_r |
| |
av_int(alist, w); |
| |
|
| |
av-float-r ( -- ) gforth av_float_r |
| |
float r = *(Float*)lp; |
| |
lp += sizeof(Float); |
| |
av_float(alist, r); |
| |
|
| |
av-double-r ( -- ) gforth av_double_r |
| |
double r = *(Float*)lp; |
| |
lp += sizeof(Float); |
| |
av_double(alist, r); |
| |
|
| |
av-longlong-r ( R:d -- ) gforth av_longlong_r |
| |
#ifdef BUGGY_LONG_LONG |
| |
av_longlong(alist, d.lo); |
| |
#else |
| |
av_longlong(alist, d); |
| |
#endif |
| |
|
| |
av-ptr-r ( R:c_addr -- ) gforth av_ptr_r |
| |
av_ptr(alist, void*, c_addr); |
| |
|
| av-call-void ( -- ) gforth av_call_void |
av-call-void ( -- ) gforth av_call_void |
| SAVE_REGS |
SAVE_REGS |
| av_call(alist); |
av_call(alist); |
| av-call-int ( -- w ) gforth av_call_int |
av-call-int ( -- w ) gforth av_call_int |
| SAVE_REGS |
SAVE_REGS |
| av_call(alist); |
av_call(alist); |
| |
REST_REGS |
| w = irv; |
w = irv; |
| |
|
| av-call-float ( -- r ) gforth av_call_float |
av-call-float ( -- r ) gforth av_call_float |
| SAVE_REGS |
SAVE_REGS |
| av_call(alist); |
av_call(alist); |
| REST_REGS |
REST_REGS |
| |
#ifdef BUGGY_LONG_LONG |
| |
d.lo = llrv; |
| |
d.hi = 0; |
| |
#else |
| d = llrv; |
d = llrv; |
| |
#endif |
| |
|
| av-call-ptr ( -- c_addr ) gforth av_call_ptr |
av-call-ptr ( -- c_addr ) gforth av_call_ptr |
| SAVE_REGS |
SAVE_REGS |
| REST_REGS |
REST_REGS |
| c_addr = prv; |
c_addr = prv; |
| |
|
| alloc-callback ( xt -- c_addr ) gforth alloc_callback |
alloc-callback ( a_ip -- c_addr ) gforth alloc_callback |
| c_addr = (char *)alloc_callback(engine_callback, ((Xt *)xt)+2); |
c_addr = (char *)alloc_callback(engine_callback, (Xt *)a_ip); |
| |
|
| |
va-start-void ( -- ) gforth va_start_void |
| |
va_start_void(clist); |
| |
|
| va-start-int ( -- w ) gforth va_start_int |
va-start-int ( -- ) gforth va_start_int |
| w = va_start_int(clist); |
va_start_int(clist); |
| |
|
| va-start-longlong ( -- d ) gforth va_start_longlong |
va-start-longlong ( -- ) gforth va_start_longlong |
| d = va_start_longlong(clist); |
va_start_longlong(clist); |
| |
|
| va-start-ptr ( -- c_addr ) gforth va_start_ptr |
va-start-ptr ( -- ) gforth va_start_ptr |
| c_addr = (char *)va_start_ptr(clist, (char *)); |
va_start_ptr(clist, (char *)); |
| |
|
| va-start-float ( -- r ) gforth va_start_float |
va-start-float ( -- ) gforth va_start_float |
| r = va_start_float(clist); |
va_start_float(clist); |
| |
|
| va-start-double ( -- r ) gforth va_start_double |
va-start-double ( -- ) gforth va_start_double |
| r = va_start_double(clist); |
va_start_double(clist); |
| |
|
| |
va-arg-int ( -- w ) gforth va_arg_int |
| |
w = va_arg_int(clist); |
| |
|
| |
va-arg-longlong ( -- d ) gforth va_arg_longlong |
| |
#ifdef BUGGY_LONG_LONG |
| |
d.lo = va_arg_longlong(clist); |
| |
d.hi = 0; |
| |
#else |
| |
d = va_arg_longlong(clist); |
| |
#endif |
| |
|
| |
va-arg-ptr ( -- c_addr ) gforth va_arg_ptr |
| |
c_addr = (char *)va_arg_ptr(clist,char*); |
| |
|
| |
va-arg-float ( -- r ) gforth va_arg_float |
| |
r = va_arg_float(clist); |
| |
|
| |
va-arg-double ( -- r ) gforth va_arg_double |
| |
r = va_arg_double(clist); |
| |
|
| va-return-void ( -- ) gforth va_return_void |
va-return-void ( -- ) gforth va_return_void |
| va_return_void(clist); |
va_return_void(clist); |
| return 0; |
return 0; |
| |
|
| va-return-longlong ( d -- ) gforth va_return_longlong |
va-return-longlong ( d -- ) gforth va_return_longlong |
| |
#ifdef BUGGY_LONG_LONG |
| |
va_return_longlong(clist, d.lo); |
| |
#else |
| va_return_longlong(clist, d); |
va_return_longlong(clist, d); |
| |
#endif |
| return 0; |
return 0; |
| |
|
| va-return-float ( r -- ) gforth va_return_float |
va-return-float ( r -- ) gforth va_return_float |
| va_return_double(clist, r); |
va_return_double(clist, r); |
| return 0; |
return 0; |
| |
|
| \- |
\+ |
| |
|
| |
\+OLDCALL |
| |
|
| define(`uploop', |
define(`uploop', |
| `pushdef(`$1', `$2')_uploop(`$1', `$2', `$3', `$4', `$5')`'popdef(`$1')') |
`pushdef(`$1', `$2')_uploop(`$1', `$2', `$3', `$4', `$5')`'popdef(`$1')') |
| \+ |
\+ |
| \+ |
\+ |
| |
|
| wcall ( u -- ) gforth |
\g peephole |
| IF_fpTOS(fp[0]=fpTOS); |
|
| FP=fp; |
|
| sp=(Cell*)(SYSCALL(Cell*(*)(Cell *, void *))u)(sp, &FP); |
|
| fp=FP; |
|
| IF_spTOS(spTOS=sp[0];) |
|
| IF_fpTOS(fpTOS=fp[0]); |
|
| |
|
| \+peephole |
\+peephole |
| |
|
| \g peephole |
|
| |
|
| compile-prim1 ( a_prim -- ) gforth compile_prim1 |
compile-prim1 ( a_prim -- ) gforth compile_prim1 |
| ""compile prim (incl. immargs) at @var{a_prim}"" |
""compile prim (incl. immargs) at @var{a_prim}"" |
| compile_prim1(a_prim); |
compile_prim1(a_prim); |
| finish-code ( -- ) gforth finish_code |
finish-code ( -- ) gforth finish_code |
| ""Perform delayed steps in code generation (branch resolution, I-cache |
""Perform delayed steps in code generation (branch resolution, I-cache |
| flushing)."" |
flushing)."" |
| |
IF_spTOS(sp[0]=spTOS); /* workaround for failing to save spTOS |
| |
(gcc-2.95.1, gforth-fast --enable-force-reg) */ |
| finish_code(); |
finish_code(); |
| |
IF_spTOS(spTOS=sp[0]); |
| |
|
| forget-dyncode ( c_code -- f ) gforth-internal forget_dyncode |
forget-dyncode ( c_code -- f ) gforth-internal forget_dyncode |
| f = forget_dyncode(c_code); |
f = forget_dyncode(c_code); |
| |
|
| \g static_super |
\g static_super |
| |
|
| \C #if !defined(GFORTH_DEBUGGING) && !defined(INDIRECT_THREADED) && !defined(DOUBLY_INDIRECT) && !defined(VM_PROFILING) |
ifdef(`M4_ENGINE_FAST', |
| |
`include(peeprules.vmg)') |
| include(peeprules.vmg) |
|
| |
|
| \C #endif |
|
| |
|
| \g end |
\g end |