home .. forth .. misc mail list archive ..

Re: Unidentified subject!


Dave Lowry's code, so far:
\ conventions:  T=accumulator, A=stack pointer, R0=reserved

VARIABLE IPSAVE		\ saved interpretation address to use upon return
VARIABLE IPNEW		\ psuedo execute address to regain control from P21forth
HERE 6 + IPNEW !

' TX!

ASSEMBLER

CODE CALL-TX!
  / some code...
  A PUSH IPSAVE # NOP
  A! POP !A IPNEW #
  A! # PUSH ;'
  IPSAVE # NOP A! @A
  A! NOP NOP NOP
  / some more code...
  NEXT
  END-CODE

Raul Miller:
>  >(1) what is IPNEW for?  Why don't you do anything with it after
>  >returning?

Dave Lowry:
>  IPNEW holds the address that I want Jeff's P21Forth word to return to.
>  In P21Forth, NEXT does @A+ PUSH ;.  IP is held implicitly in the A
>  register.  So, I put the address I want to return to in IPNEW, and the
>  address of IPNEW in A, then call a P21Forth word.  By the way, the code
>  fragment I posted *does* work, I'm just looking for a better way.

Ah ha!  This makes a lot more sense now.

>  >(2) do you really mean for this code to be non reentrant?

>  No, that's why I'm asking the question.  The fragment above would
>  require a different IPSAVE and IPNEW for each instantiation.  I'm
>  wondering if there's a better way.

see below.

>  >(6) Don't you think that A! and + should automatically insert nops
>  >where needed?

>  Huh?  I have placed a NOP before A!, unless it is the first
>  instruction.  This is, to my understanding, correct.

Sure.  I was refering to changing the CODE compiler to make it easier
to write code.  Sorry I didn't make that clear.

>  >Presuming the easy answers to these questions, I'd probably generate
>  >code like:
>  >   varref ipsave
>  >   varref ipnew
>  >   varref calladdr
>  >...
>  >   ipsave # a<->tos !a #ipnew a! #calladdr push ;' #ipsave a! @a a!

>  Umm, isn't this exactly what I've done above?  I'm missing your point.

Well, it's functionally identical except that

(a) the storage for ipsave is inline, and
(b) I messed up and stuffed the value of ipnew in A rather than the
    address of ipnew.

The big difference is that I'm putting the variables in-line.  Call it
self modifying code if you like -- though it's quite structured in
actual practice.  I represent inline variables in the above code by
marking the actual location of a variable with a preceeding # as part
of the word.  I'm visuallizing a forth where the outer interpreter has
been modified to attempt to resolve words spelled #varref if
dictionary lookup fails and before attempting to interpret them as
numbers.  Since the P21 requires you copy pretty much everything from
rom to ram before execution, I don't think there are any major
drawbacks to this technique -- except that this is not yet supported
in the current batch of P21 compilers.

However, what I think you're asking for is a way of putting ipnew and
ipsave on the stack?

How about we talk about this in terms of data structures for a bit
before trying to implement code?

You've got some C environment you wish to save when you call a
P21Forth routine.  You've indicated above that that's likely to be A,
T, and R0.  A presumably points to the bottom of some region would
ordinarily be used as a scratch area (it's the stack pointer).  R0 and
T we can leave alone, because P21Forth already saves those.

To call P21Forth you need to leave your arguments on the stack
(because that's where it will look for them).  Furthermore, P21Forth
may trash what's above the stack pointer before returning.  This seems
to mean that you don't have any stack left to work with (since C
doesn't have an R stack).  But wait -- what about the possibility that
P21Forth will need to use the R stack?  You're going to have to
address this somehow.

I think that a reusable/reentrant solution to this problem should be
intimately related to your handling of this R stack issue.

Over to you..


-- 
Raul D. Miller