Jump to content
IGNORED

TurboForth V1.2 (Beta)--Evolution & Arcana


Lee Stewart

Recommended Posts

 

 

Doh! :dunce: Sometimes I feel so stupid. I knew that about scroll lock. It's just not automatic, yet. I had set breakpoints at 2000h and 2008h and, as you said, Classic99 didn't stop until it hit 2008h. Thanks, again! :)

 

...lee

 

Cool! Just remember there's no executable code at the vector address - it's data! I've been caught by that before in one of my many blonde moments!

Link to comment
Share on other sites

R1 STST,

 

Is that what you want? You're fetching the status register from TurboForth's context, not your fp context.

 

If you want the status register from the fp context then you need to save it somewhere prior to the return to tf context( I. E prior to the rtwp instruction on the FP side)

 

Hope I'm not teaching you to suck eggs here!

 

I do understand, I think. Prior to the RTWP from the FPL library, the status is stored in R15 so that when it returns, it is in the status register. So, yes, I do want the current context's status. :P I do appreciate any and all assistance. You just never know what I may or may not know. You can rest assured that your knowledge in that regard is more than mine.

 

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

Yes I did sorry! I forgot to put it back( I wanted the system to stay in 80 column mode)

 

: EDIT 2 GMODE EDIT 0 GMODE ;

 

Thank you, Sir! Actually, I was beginning to worry that you had slipped to an earlier BLOCKS file because other things were going wrong; but, I decided to reboot my computer because I'd had it on for many days (weeks?). It seems OK now.

 

...lee

Link to comment
Share on other sites

I do understand, I think. Prior to the RTWP from the FPL library, the status is stored in R15 so that when it returns, it is in the status register. So, yes, I do want the current context's status. :P I do appreciate any and all assistance. You just never know what I may or may not know. You can rest assured that your knowledge in that regard is more than mine.

 

...lee

 

Sorry to labour the point, just wanted to check lest it save you grey hairs later on!

 

When you do a BLWP is does a 'context switch' - that is the current execution "context" (workspace pointer, pc and status register) are saved in R13 R14 & R15 of the *new* workspace, so that they can be restored with a RTWP (thus restoring the previous execution context).

 

My suspicion is that your intention, with the STST instruction, is to get the status register value from your FPL's execution context. If that is the case, then you need to store it somewhere so that you can get it back post RTWP, "on the TurboForth side" of the code. You might as well save it in R0, I guess...

 

So, in the FPL library (before your RTWP):

 

R13 ** STST,1

RTWP

 

Which fully restores TF's execution context (i.e. restores workspace, PC and SR) and has the status register value from your FP subroutine in TF's R0, ready for checking.

 

Which will place the status register value in the address pointed to by R13, which is R0 of TF's workspace. Now you can get the FPL status register 'on the TF side' by looking in R0.

 

1 - I can't remember, it might not be possible to use indirection with STST - so you might have to use an intermediate register:

R0 STST,

R0 *R13 MOV,

 

If this is already crystal clear then I humbly apologise!

Link to comment
Share on other sites

Sorry to labour the point, just wanted to check lest it save you grey hairs later on!

 

When you do a BLWP is does a 'context switch' - that is the current execution "context" (workspace pointer, pc and status register) are saved in R13 R14 & R15 of the *new* workspace, so that they can be restored with a RTWP (thus restoring the previous execution context).

 

My suspicion is that your intention, with the STST instruction, is to get the status register value from your FPL's execution context. If that is the case, then you need to store it somewhere so that you can get it back post RTWP, "on the TurboForth side" of the code. You might as well save it in R0, I guess...

 

So, in the FPL library (before your RTWP):

 

R13 ** STST,1

RTWP

 

Which fully restores TF's execution context (i.e. restores workspace, PC and SR) and has the status register value from your FP subroutine in TF's R0, ready for checking.

 

Which will place the status register value in the address pointed to by R13, which is R0 of TF's workspace. Now you can get the FPL status register 'on the TF side' by looking in R0.

 

1 - I can't remember, it might not be possible to use indirection with STST - so you might have to use an intermediate register:

R0 STST,

R0 *R13 MOV,

 

If this is already crystal clear then I humbly apologise!

 

The last thing the FPL does before returning via RTWP is STST R15. This has the effect of "restoring" the FPL's SR to TF's SR so that TF can check the status of the last FPL instruction that affected status. This may not be important for any FPL function except FCOMP (floating point compare), which relies on it.

 

I can't use TF's R0 for anything because that's the FPL's error return for all functions. I don't need to store the status until the GPL returns, anyway (see last ¶).

 

Your footnote is correct, which is the reason for my similar statements after the return from the FPL.

 

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

Floating Point Library (FPLTF)---

 

MONUMENTAL PROGRESS!!! :-o

 

I successfully loaded the FPL and all of my modifications of @Willsy's TF code! Better than that, I can enter FP numbers with >F and get them back with F. , so I don't have to monkey around with helper words (yet) to get me around any general problems. I have a small problem with .FS I must work out; but, things are definitely looking up!

 

Being able to see what I'm doing will now allow me to knock out the testing of each function in short order.

 

...lee

  • Like 1
Link to comment
Share on other sites

Floating Point Library (FPLTF)---

 

Yet Another Progress Report (YAPR):

 

Everything appears to be working except for some of the transcendental functions. I haven't checked them all, yet:

  • INT works.
  • LOG fails.
  • POW works for integral exponents, but fails for non-integral exponents. This failure is probably due to the failure of LOG , which POW uses for non-integral exponents.
  • SQR fails. It does not call LOG , so something else is wrong.

The errors I've discovered so far in the FPL library have been erroneous changes I had made to the FPL to use FAC and ARG to pass parameters as well as changes to how the ASCII string information is passed back and forth. I suspect that is what I'll find for the failing transcendentals, too.

 

One word that probably did not work in the previous incarnation of TF's FP library is F= . There was an = between AND and IF that should have caused a stack underflow, but simply left nothing on the stack. It would likely have caused such an error had an attempt been made to consume the result. My current definition follows:

 

: F= ( -- t/f | a b -- )

0 doComp

FPSTAT C@ %00100000 AND IF TRUE ELSE FALSE THEN ;

 

The only real difference between this word (now working) and @Willsy's previous word is the now removed = . Moving right along...

 

...lee

Link to comment
Share on other sites

Nice job Lee and nice job spotting the error. If I'm not mistaken there is a further opportunity to save some bytes and speed in the above code: I think a simple 0> can replace the entire IF TRUE ELSE FALSE THEN sequence!

 

What was I thinking when I wrote it?!

Link to comment
Share on other sites

Nice job Lee and nice job spotting the error. If I'm not mistaken there is a further opportunity to save some bytes and speed in the above code: I think a simple 0> can replace the entire IF TRUE ELSE FALSE THEN sequence!

 

What was I thinking when I wrote it?!

 

Thanks. I'll include that change.

 

One thing that troubles me about the FPL is that some of the transcendental functions take an interminably long time to execute. I hope it's mostly due to errors I haven't yet discovered, but I'm not holding my breath. The polynomial evaluations of many of the transcendentals use up to 4 temporary FP numbers. I think I am going to move them to SP memory if I can find 32 bytes that fixSP can be made to restore.

 

...lee

Link to comment
Share on other sites

More FPL stuff---

 

H-m-m-m...I think the following will work nicely:

 

: F= ( -- t/f | a b -- ) 0 doComp FPSTAT C@ %00100000 AND 0> ;

: F0= ( -- t/f | a -- ) fpsc-- fpsaddr @ 0= ;

: F> ( -- t/f | a b -- ) 0 doComp FPSTAT C@ %01000000 AND 0> ;

: F< ( -- t/f | a b -- ) FSWAP F> ;

: F0< ( -- t/f | a -- ) fpsc-- fpsaddr @ 0< ;

 

What do you think, Mark, about replacing the code for F< with

 

: F<
( -- t/f | a b -- )
0 doComp FPSTAT C@ %01100000 AND 0= ;

 

The FWSAP wastes time, I think.

 

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

Well, I don't know the meaning of the bits coming back from FPSTAT. But if you think it's right and it saves time I say give it a try.

 

Also, this leapt out at me:

 

0 doComp FPSTAT C@ %01100000 AND 0=

 

The stuff in red is common to three of your definitions. Is that going to be a common theme? If so, it's a good candidate for factoring into its own definition. Maybe getStat :

 

: getStat ( mask -- n )

0 doComp FPSTAT C@ SWAP AND ;

 

Meaning that (for example) F= becomes:

 

: F= ( -- t/f | a b -- ) %00100000 getStat 0> ;

 

Which I quite like. I like information hiding. It's Forthy and it would be an improvement over my original code. If it's a common enough occurrence I'd even consider making it a machine code subroutine. :)

 

However, if you think it's overkill then fair enough!

Link to comment
Share on other sites

What do you think, Mark, about replacing the code for F< with

 

: F< ( -- t/f | a b -- ) 0 doComp FPSTAT C@ %01100000 AND 0= ;

 

Okay, so if the GT and COND bits are off then it's a < condition, right? What's the meaning of the COND bit in the context of floating point? It's re-purposed for something else when used for FP IIRC but I can't remember its designation.

Link to comment
Share on other sites

Okay, so if the GT and COND bits are off then it's a < condition, right? What's the meaning of the COND bit in the context of floating point? It's re-purposed for something else when used for FP IIRC but I can't remember its designation.

 

I'll have to think on that one. Right now, it's out to dinner with my Love! TTFN

 

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

Okay, so if the GT and COND bits are off then it's a < condition, right? What's the meaning of the COND bit in the context of floating point? It's re-purposed for something else when used for FP IIRC but I can't remember its designation.

 

No bits are re-purposed. We are using the TMS9900's status register, which, as you know, the GPL status byte is a copy of after returns from GROM and the EQ bit is called the COND bit. That's all. The status register value of the last comparison made by the FP compare routine is stashed in R15 with STST R15 just before returning with a context switch to the TF environment via RTWP. The comparison with 0 only needs to check the first word of FAC because that word tells the whole story. It is 0 when the number is 0, negative when the number is negative and positive when the number is positive. For comparison of 2 numbers (FAC and ARG), if they are of opposite sign, the comparison, once again, is limited to the first word. If they have the same sign, they are both insured to be positive (number order is probably reversed for 2 negative numbers so the SR for the last check will be valid) and the comparison goes byte by byte until they are determined unequal or the end of the FP numbers is reached, in which case they are equal. Again, whatever the status that last comparison generates, that's the one that gets stashed in R15 and winds up in the SR immediately after the return to TF.

 

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

Well, I don't know the meaning of the bits coming back from FPSTAT. But if you think it's right and it saves time I say give it a try.

 

Also, this leapt out at me:

 

0 doComp FPSTAT C@ %01100000 AND 0=

 

The stuff in red is common to three of your definitions. Is that going to be a common theme? If so, it's a good candidate for factoring into its own definition. Maybe getStat :

 

: getStat ( mask -- n )

0 doComp FPSTAT C@ SWAP AND ;

 

Meaning that (for example) F= becomes:

 

: F= ( -- t/f | a b -- ) %00100000 getStat 0> ;

 

Which I quite like. I like information hiding. It's Forthy and it would be an improvement over my original code. If it's a common enough occurrence I'd even consider making it a machine code subroutine. :)

 

However, if you think it's overkill then fair enough!

 

No...I like that, too! Oh, and we don't need the SWAP . It won't change anything.

 

doComp (do comparison) is only used in those 3 places, but your suggestion saves space, so I should call that doComp and expand it as shown at the bottom below. All we need to do is to roll your suggestion into it. FYI, following are goFPL , fixSP and the helper functions that call goFPL :

 

 

\ link to Floating Point Library for TurboForth

\ ---expects FAC, ARG and _fpstr already set up

ASM: goFPL ( FPL_fxn -- )

*SP+ R0 MOV, \ get function # to R0

R1 _fpstr LI, \ point R1 to FP string buffer whether we need it or not

FPLLNK @@ BLWP, \ link to FPL

R1 STST, \ get FP status

R1 FPSTAT @@ MOV,

R0 FPERR @@ MOV, \ get FP error

;ASM

 

ASM: fixSP \ restore scratchpad memory

$6000 @@ CLR, \ select bank 1

$A010 @@ R0 MOV, \ scratchpad restore code vector

R0 ** BL, \ restore scratchpad

$6002 @@ CLR, \ select bank 0

;ASM

 

\ invoke goFPL with 1 variable on FP stack

\ ---expects _fpstr already set up if needed

: goFPL_1var ( ds:FPL_fxn -- fs:a -- )
fps>fac goFPL fac>fpstack fixSP ;

 

\ invoke goFPL with 2 variables on FP stack

\ ---expects _fpstr already set up if needed

: goFPL_2vars ( ds:FPL_fxn -- fs:a b -- )
fps>fac fps>arg goFPL fac>fpstack fixSP ;

 

\ invoke goFPL with 2 variables on FP stack, but no return in FAC

: doComp ( ds:FPL_fxn -- fs:a b -- )
fps>fac fps>arg goFPL fixSP ;

 

The new doComp would be

 

: doComp ( ds:mask -- n fs:a b -- )
fps>fac fps>arg 0 goFPL fixSP FPSTAT C@ AND ;

 

 

...lee

Link to comment
Share on other sites

Floating Point Library---

 

OK...so, now for the comparison functions, we have

 

: doComp ( ds:mask -- n fs:a b -- )
fps>fac fps>arg 0 goFPL fixSP FPSTAT C@ AND ;

 

: F= ( -- t/f | a b -- ) %00100000 doComp 0> ;

: F0= ( -- t/f | a -- ) fpsc-- fpsaddr @ 0= ;

: F> ( -- t/f | a b -- ) %01000000 doComp 0> ;

: F< ( -- t/f | a b -- ) %01100000 doComp 0= ;

: F0< ( -- t/f | a -- ) fpsc-- fpsaddr @ 0< ;

 

Pretty compact, I'd say.

 

...lee

Link to comment
Share on other sites

Floating Point Library---

 

YAPR: This is a BIG one!!! I found 2 insidious errors I had made where I was trying to save time! Now, pretty much everything I'm checking in the transcendental functions is working! WooHoo!! :-o :grin:

 

FYI, the errors were the same. I had substituted a BL @R1$2 and RT for three MOV *R1+,*R2+ and one MOV *R1,*R2 instructions. The problem was that two of those sets of MOVs ended with MOV *R1+,*R2!!! Restoring the original 8 instructions brings the FPL size to 5652 bytes.

 

I will soon be working on extending the display functions to allow for some formatting of output, including one that allows 3 display places for the exponent.

 

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

Wow! Congratulations Lee! You're really blazing the trail now! :thumbsup: :thumbsup:

 

I don't know about you, but I've found developing assembly code in a Forth environment to be a real pleasure; just having the command line there and being able to tap out colon defs to test your work, and even write assembly right there at the keyboard is a massive advantage over the 'standard' way of doing it with the Editor Assembler.

 

Of course, the same applies to TI Forth. Not just TurboForth. In fact, TF's assembler is a port of the TI Forth assembler! :grin:

 

Good job!

 

Of course, once you have written the code, you'll have to write the documentation! :P

Link to comment
Share on other sites

Wow! Congratulations Lee! You're really blazing the trail now! :thumbsup: :thumbsup:

 

Thanks! :)

 

I don't know about you, but I've found developing assembly code in a Forth environment to be a real pleasure; just having the command line there and being able to tap out colon defs to test your work, and even write assembly right there at the keyboard is a massive advantage over the 'standard' way of doing it with the Editor Assembler.

 

Yes, indeed! :grin:

 

Of course, the same applies to TI Forth. Not just TurboForth. In fact, TF's assembler is a port of the TI Forth assembler! :grin:

 

Good job!

 

Of course, once you have written the code, you'll have to write the documentation! :P

 

Yeah, well! |:)

 

...lee

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...