+Lee Stewart Posted October 6, 2020 Author Share Posted October 6, 2020 1 hour ago, TheBF said: Lee we had discussed creating faster dictionary searches using a hashing method like PolyForth. I found this book by Dr. Ting called inside Forth83, which is a fantastic little Forth for DOS by Laxen & Perry. It used a 4 way hash on the dictionary which is described herein. Here is the link to the book: http://www.forth.org/OffeteStore/1003_InsideF83.pdf. Page 73 shows real code on how they Laxen and Perry did it .... Sounds interesting. I must check it out. Thanks. ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted October 14, 2020 Author Share Posted October 14, 2020 (edited) The comments by @Tursi and @Asmusr regarding methods of calculating square roots sparked a Google search, which netted the algorithm I used in the following fast routine for the square root of an unsigned double number (from Craig McQueen’s response to “Looking for an efficient integer square root algorithm for ARM Thumb2” on stackoverflow.com) : Spoiler HEX \ Registers: R0,R1 = udh,udl \ R2,R3 = root (nh,nl) \ R4,r5 = floating 1 (f1h,f1l) \ R6,R7 = wkh,wkl ASM: UDSQRT ( ud -- n ) *SP+ R0 MOV, \ pop udh to R0 *SP R1 MOV, \ udl to R1 R2 CLR, \ clear running.. R3 CLR, \ ..root (nh,nl) R5 CLR, \ set floating 1.. R4 4000 LI, \ ..to 4000 0000 \ get highest power of 4 <= square (udh,udl) BEGIN, R4 R0 C, \ f1h:udh? EQ IF, R5 R1 C, \ f1l:udl? THEN, H WHILE, R4 R5 C, \ f1h:f1l? H IF, \ bit in f1h? R4 2 SRL, \ yes..shift f1h right 2 bits EQ IF, \ bit shifted out? R5 4000 LI, \ set f1l to shifted-out bit THEN, ELSE, \ no..bit is in f1l R5 2 SRL, \ shift f1l right 2 bits THEN, REPEAT, \ calculate square root BEGIN, R4 R5 C, \ f1h:f1l? NE WHILE, \ f1h,f1l > 0? \ set up wkh,wkl = nh,nl + f1h,f1l to compare to udh,udl R2 R6 MOV, \ nh to wkh R3 R7 MOV, \ nl to wkl R5 R7 A, \ f1l + wkl OC IF, \ carry? R6 INC, \ yes..increment wkh THEN, R4 R6 A, \ f1h + wkh \ check if need to update running values of udh,udl & nh,nl R0 R6 C, \ udh:wkh? EQ IF, \ udh = wkh? R1 R7 C, \ udl:wkl? THEN, HE IF, \ udh,udl >= wkh,wkl? \ udh,udl = udh,udl - wkh,wkl R7 R1 S, \ udl - wkl NC IF, R0 DEC, \ reduce udh on no carry THEN, R6 R0 S, \ udh - wkh \ nh,nl = wkh,wkl + f1h,f1l R5 R7 A, \ wkl + f1l OC IF, \ carry? R6 INC, \ yes..increment wkh THEN, R4 R6 A, \ wkh + f1h R6 R2 MOV, \ wkh to nh R7 R3 MOV, \ wkl to nl THEN, \ f1h,f1l >> 2 R4 R5 C, \ f1h:f1l? H IF, \ bit in f1h? R4 2 SRL, \ yes..shift f1h right 2 bits EQ IF, \ bit shifted out? R5 4000 LI, \ set f1l to shifted-out bit THEN, ELSE, \ no..bit is in f1l R5 2 SRL, \ shift f1l right 2 bits THEN, \ nh,nl >> 1 R3 1 SRL, \ shift nl right 1 bit R2 1 SRL, \ shift nh right 1 bit OC IF, \ carry? R3 8000 ORI, \ set MSb of nl THEN, REPEAT, R3 *SP MOV, \ return n on stack ;ASM This routine (UDSQRT) is 128 bytes long, but is very fast. Even for the highest unsigned double number possible, FFFF FFFF16 (4,294,967,29510), it is a mere hesitation—quicker than I could manage a stopwatch. It uses a binary version of the paper-and-pencil method of working out square roots we learned in grade school. The result is truncated rather than rounded. The basis for the above code is this C routine: Spoiler /** * \brief Fast Square root algorithm * * Fractional parts of the answer are discarded. That is: * - SquareRoot(3) --> 1 * - SquareRoot(4) --> 2 * - SquareRoot(5) --> 2 * - SquareRoot(8) --> 2 * - SquareRoot(9) --> 3 * * \param[in] a_nInput - unsigned integer for which to find the square root * * \return Integer square root of the input value. */ uint32_t SquareRoot(uint32_t a_nInput) { uint32_t op = a_nInput; uint32_t res = 0; uint32_t one = 1uL << 30; // The second-to-top bit is set: use 1u << 14 for uint16_t type; use 1uL<<30 for uint32_t type // "one" starts at the highest power of four <= than the argument. while (one > op) { one >>= 2; } while (one != 0) { if (op >= res + one) { op = op - (res + one); res = res + 2 * one; } res >>= 1; one >>= 2; } return res; } ...lee Edited October 14, 2020 by Lee Stewart Inclusion of Source Credits 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted October 14, 2020 Share Posted October 14, 2020 Albert Van der Horst did a pile of work on this for his ciForth system. It's on comp.lang.forth. I will see if I can find a Forth version for comparison. Quote Link to comment Share on other sites More sharing options...
+TheBF Posted October 14, 2020 Share Posted October 14, 2020 I found it but it needs a pile of library code from his system and I think it is for 64 bit integers so it will choke on our favourite CPU. https://groups.google.com/g/comp.lang.forth/c/j_8Bdl7-c_s/m/j-J3E_NjAQAJ Incomprehensible to me. Spoiler 1,000,000,013 CONSTANT p WANT SQ SQRT FACTOR GCD PRIME? WANT REGRESS \ For N return FLOOR of the square root of n. VARIABLE T 1000 T ! : SQRT1 >R T @ R@ OVER / + 2/ \ Minimize iterations. BEGIN R@ OVER / OVER + 2/ .S 2DUP > WHILE NIP REPEAT DROP RDROP DUP T ! ; REGRESS 1001 SQRT S: 31 REGRESS 81 SQRT S: 9 \ For N return :" n IS a square" VARIABLE T_s 1000 T_s ! : SQ? >R T_s @ R@ OVER / + 2/ \ Minimize iterations. BEGIN R@ OVER / OVER + 2/ .S 2DUP > WHILE NIP REPEAT DUP T_s ! * R> = ; REGRESS 1001 SQ? S: 0 REGRESS 81 SQ? S: -1 : hart DUP 1 DO KEY? IF RDROP LEAVE THEN DUP I M* THROW SQRT1 1+ DUP >R \ s SQ OVER MOD \ m DUP SQ? .S IF SQRT \ t R> SWAP - OVER GCD LEAVE ELSE R> 2DROP THEN .S LOOP ; Quote Link to comment Share on other sites More sharing options...
+TheBF Posted October 14, 2020 Share Posted October 14, 2020 56 minutes ago, Lee Stewart said: The comments by @Tursi and @Asmusr regarding methods of calculating square roots sparked a Google search, which netted the algorithm I used in the following fast routine for the square root of an unsigned double number (I need to search again to give due credit): Hide contents HEX \ Registers: R0,R1 = udh,udl \ R2,R3 = root (nh,nl) \ R4,r5 = floating 1 (f1h,f1l) \ R6,R7 = wkh,wkl ASM: UDSQRT ( ud -- n ) *SP+ R0 MOV, \ pop udh to R0 *SP R1 MOV, \ udl to R1 R2 CLR, \ clear running.. R3 CLR, \ ..root (nh,nl) R5 CLR, \ set floating 1.. R4 4000 LI, \ ..to 4000 0000 \ get highest power of 4 <= square (udh,udl) BEGIN, R4 R0 C, \ f1h:udh? EQ IF, R5 R1 C, \ f1l:udl? THEN, H WHILE, R4 R5 C, \ f1h:f1l? H IF, \ bit in f1h? R4 2 SRL, \ yes..shift f1h right 2 bits EQ IF, \ bit shifted out? R5 4000 LI, \ set f1l to shifted-out bit THEN, ELSE, \ no..bit is in f1l R5 2 SRL, \ shift f1l right 2 bits THEN, REPEAT, \ calculate square root BEGIN, R4 R5 C, \ f1h:f1l? NE WHILE, \ f1h,f1l > 0? \ set up wkh,wkl = nh,nl + f1h,f1l to compare to udh,udl R2 R6 MOV, \ nh to wkh R3 R7 MOV, \ nl to wkl R5 R7 A, \ f1l + wkl OC IF, \ carry? R6 INC, \ yes..increment wkh THEN, R4 R6 A, \ f1h + wkh \ check if need to update running values of udh,udl & nh,nl R0 R6 C, \ udh:wkh? EQ IF, \ udh = wkh? R1 R7 C, \ udl:wkl? THEN, HE IF, \ udh,udl >= wkh,wkl? \ udh,udl = udh,udl - wkh,wkl R7 R1 S, \ udl - wkl NC IF, R0 DEC, \ reduce udh on no carry THEN, R6 R0 S, \ udh - wkh \ nh,nl = wkh,wkl + f1h,f1l R5 R7 A, \ wkl + f1l OC IF, \ carry? R6 INC, \ yes..increment wkh THEN, R4 R6 A, \ wkh + f1h R6 R2 MOV, \ wkh to nh R7 R3 MOV, \ wkl to nl THEN, \ f1h,f1l >> 2 R4 R5 C, \ f1h:f1l? H IF, \ bit in f1h? R4 2 SRL, \ yes..shift f1h right 2 bits EQ IF, \ bit shifted out? R5 4000 LI, \ set f1l to shifted-out bit THEN, ELSE, \ no..bit is in f1l R5 2 SRL, \ shift f1l right 2 bits THEN, \ nh,nl >> 1 R3 1 SRL, \ shift nl right 1 bit R2 1 SRL, \ shift nh right 1 bit OC IF, \ carry? R3 8000 ORI, \ set MSb of nl THEN, REPEAT, R3 *SP MOV, \ return n on stack ;ASM This routine (UDSQRT) is 128 bytes long, but is very fast. Even for the highest unsigned double number possible, FFFF FFFF16 (4,294,967,29510), it is a mere hesitation—quicker than I could manage a stopwatch. It uses a binary version of the paper-and-pencil method of working out square roots we learned in grade school. The result is truncated rather than rounded. ...lee That's a thing of beauty. 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 23, 2021 Author Share Posted January 23, 2021 I finally got around to testing a pre-release of fbForth 2.0:13 on real iron with a 4 MiB SAMS card in a PEB. It was not an exhaustive test, but it did correctly determine that its capacity is 4 MiB. The only remaining item before release is whether I should change SPRDIST and SPRDISTXY to calculate the actual distance (rather than its square) by including UDSQRT (see my last post). It looks like I may be able to squeeze it into the remaining space in bank #1. Not only would it make sense to use actual distances, but it would also allow using all distances that are possible, including those that are too large to be represented by a signed, 16-bit integer. The square of a distance between 182 and 318 pixels (all possible) currently must be forced to 32767 (>7FFF). One hesitation is that it would break compatibility with TI Forth and old fbForth code that relies on the present distance representation. Another is that it might present a problem for coincidence calculations for small distances because UDSQRT truncates the result. I might have enough room to rectify that, however. Thoughts? ...lee 1 1 Quote Link to comment Share on other sites More sharing options...
atrax27407 Posted January 23, 2021 Share Posted January 23, 2021 My only thought is "just let me know when it is ready". 1 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted January 24, 2021 Share Posted January 24, 2021 10 hours ago, Lee Stewart said: I finally got around to testing a pre-release of fbForth 2.0:13 on real iron with a 4 MiB SAMS card in a PEB. It was not an exhaustive test, but it did correctly determine that its capacity is 4 MiB. The only remaining item before release is whether I should change SPRDIST and SPRDISTXY to calculate the actual distance (rather than its square) by including UDSQRT (see my last post). It looks like I may be able to squeeze it into the remaining space in bank #1. Not only would it make sense to use actual distances, but it would also allow using all distances that are possible, including those that are too large to be represented by a signed, 16-bit integer. The square of a distance between 182 and 318 pixels (all possible) currently must be forced to 32767 (>7FFF). One hesitation is that it would break compatibility with TI Forth and old fbForth code that relies on the present distance representation. Another is that it might present a problem for coincidence calculations for small distances because UDSQRT truncates the result. I might have enough room to rectify that, however. Thoughts? ...lee Could you make the new distance calculator a block on the disk and people can use it if they need it? Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 24, 2021 Author Share Posted January 24, 2021 3 minutes ago, TheBF said: Could you make the new distance calculator a block on the disk and people can use it if they need it? Certainly. ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted January 24, 2021 Share Posted January 24, 2021 1 minute ago, Lee Stewart said: Certainly. ...lee Does that way not appeal to you? 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 24, 2021 Author Share Posted January 24, 2021 12 hours ago, TheBF said: Does that way not appeal to you? At this point, I would call it my second choice. It just grates on me to use the square of the distance as the distance—and a flawed (limited) value, at that. The compatibility issue is really all that is holding me back. I will likely take your suggestion, in the end. ...lee 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted February 3, 2021 Author Share Posted February 3, 2021 Gettin’ there! This test did just fine on real iron with a 4 MiB SAMS card: HEX EAF0 S0&TIB! DROP \ S0 and TIB to >EAF0 \ Map SAMS to >F000. \ Write the SAMS bank # to >F800 for every 16th bank, \ starting with bank #>000F (pass-through). : SAMSW ( -- ) SAMS? 00F DO I F000 >MAP \ map next SAMS bank I F800 ! \ store current bank # 010 +LOOP ; \ Read back what SAMSW wrote. : SAMSR ( -- ) SAMS? 0F DO I F000 >MAP \ map next SAMS bank F800 ? \ print value stored by SAMSW 010 +LOOP ; \ Do it... SAMSW SAMSR ...lee 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted February 3, 2021 Share Posted February 3, 2021 Did you skip every by 16 banks just to save some time? Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted February 3, 2021 Author Share Posted February 3, 2021 58 minutes ago, TheBF said: Did you skip every by 16 banks just to save some time? Yes and no. I wanted to see it all on one screen without having to write in a pause or write and run a true memory test, which would have taken quite a while. You see, I have no convenient way to transfer code to diskette from PC. Composing and testing on the 4A would have been a chore. I may do that tomorrow, though. It would be nice to run a full test. Nonetheless, I did accomplish my main goal of proving the SAMS card was operational and that the SAMS words were operating as they should. ...lee 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted February 3, 2021 Share Posted February 3, 2021 I have been using magic file manipulator. It's a little tedious but it works ok. Bought an off the shelf RS232 cable and it worked first time. Never had that happen before. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted February 20, 2021 Author Share Posted February 20, 2021 I have fbForth 2.0:13 ready to be ZIPped up and will try to get it posted tomorrow. I have FBLOCKS (19FEB2021) ready to go, as well. I put UDSQRT in block 57, See post #1652ff for details. ( I am still thinking of changing fbForth 2.0 in a later build to use actual distances instead of squares of distances for SPRDIST SPRDISTXY DXY COINC COINCXY after more discussion regarding breaking code ported from TI Forth that might use those words. After all, that is the only reason I hesitate doing it—and that just might not be a realistic consideration. ) ...lee 3 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted February 21, 2021 Share Posted February 21, 2021 On 2/19/2021 at 11:01 PM, Lee Stewart said: I have fbForth 2.0:13 ready to be ZIPped up and will try to get it posted tomorrow. I have FBLOCKS (19FEB2021) ready to go, as well. I put UDSQRT in block 57, See post #1652ff for details. ( I am still thinking of changing fbForth 2.0 in a later build to use actual distances instead of squares of distances for SPRDIST SPRDISTXY DXY COINC COINCXY after more discussion regarding breaking code ported from TI Forth that might use those words. After all, that is the only reason I hesitate doing it—and that just might not be a realistic consideration. ) ...lee Does the distance computation affect the coincidence performance much or was this more an academic exercise to show it could be done? Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted February 21, 2021 Author Share Posted February 21, 2021 3 hours ago, TheBF said: Does the distance computation affect the coincidence performance much or was this more an academic exercise to show it could be done? That depends on a programmer’s use of coincidence. It surely does not affect the coincidence performance much (or at all) because coincidence is probably never used for anything very far from the object of interest, i.e., the coincidence tolerance likely never comes anywhere near 181 pixels, which is the limit of the current calculations because dx2, dy2 and dx2+dy2 are all limited to the highest positive integer, 32767 (1812 = 32761). The mathematical limit is 318 pixels, corner to corner (object1 [0,0] and object2 [255,191] or object1 [0,191] and object2 [255,0]). Right now, SPRDIST is used by COINC and SPRDISTXY is used by COINCXY and both use DXY for their calculations. In fact, the existence of DXY is solely as an intermediary for SPRDIST and SPRDISTXY calculations. DXY only appears in the glossary. Its use is not discussed anywhere else in the TI Forth and fbForth manuals. If I can cram it all into the ROM, I would change the calculations to use actual distances. The other alternative would be to let the user change a flag to use whichever of the two methods they desire—much as I do now with S|F to determine whether M/ uses SM/REM (symmetric division) or FM/MOD (floored division). Again, if I can cram it all into the ROM, this is the way I will do it. For the moment, though, I must focus on packaging fbForth 2.0:13 stuff for release for all of you programmers champing at the bit to get your hands on it. ...lee 4 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted February 23, 2021 Author Share Posted February 23, 2021 Finally!! Post #1 has been updated with all of the files for the latest build, fbForth 2.0:13. I will update my website ere long. I will post changes for this build later—gotta get to bed. ...lee 4 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted February 23, 2021 Author Share Posted February 23, 2021 Post #1 has become pretty cluttered with older files, which most folks will probably never need, and I have been meaning to clean it up, but have put it off until now, when I was made aware of the confusion it has caused. If anyone needs older files, I will provide them upon request. ...lee 3 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 27, 2021 Share Posted April 27, 2021 FbForth multi-tasker (untested) This has never been compiled but I looked through the manual to get some magic numbers. I am sure it is full of mistakes but the idea is there. The first thing that needs to be tested is: 1. Run INIT-MULTI 2. Run PAUSE Nothing should happen. This will just do a context switch from Forth to the same Forth. But if it does that switch is means it remembers the context and gets back to itself . Then the rest is simply making a copy of the USER area in another place, tacking on some space for stacks and linking to the round-robin list. FORK does all that, at least that's the design. Not sure if you have any interest but its a start. For all the assistance you provide this is a small thank you. I will need to make a working FbForth folder to actually debug it but you can see the warts pretty quickly to rough it in. \ TASKS99.FTH for FbFORTH 27 APR2021 Brian Fox \ Loosely derived from COOPTASK.MAX for MaxForth 68HC11 B Fox 1992 \ This is a conventional Forth multi-tasker using a single workspace \ with separate data stacks, return stack and user area for each task. \ It is interesting to note that the Forth virtual machine uses 3 registers \ for context,two stack pointers and the instruction pointer and the TMS9900 \ also uses 3 registers for context, WP, PC and ST. FORTH DEFINITIONS CODE ME ( -- addr) \ orignal name was MYSElf. Already used in FigForth SP DECT, UP *SP MOV, NEXT, ENDCODE ME CONSTANT USER0 \ USER0 is the primary Forth task \ add these two user variables to FbFORTH HEX 6E USER RSAVE \ temp storage for RP register when we change tasks 70 USER TFLAG \ flag that indicates task is awake or asleep 72 USER TLINK \ link to the next task in the round-robin queue of user-pointers 74 USER JOB \ XT of the what the task is running. Handy for re-starting \ Coventional Forth Pause ASSEMBLER DEFINITIONS : @(UP) R8 () ; \ rename for assembler FORTH DEFINITIONS CODE PAUSE ( -- ) \ this is the context switcher RP DECT, SP RP ** MOV, \ push my SP register RP DECT, IP RP ** MOV, \ push my IP register RP 6E @(UP) MOV, \ save my return stack pointer in LOCAL RSAVE user-var BEGIN, 72 @(UP) R8 MOV, \ load the next task's UP into CPU UP (context switch) 70 @(UP) 0 CI, \ test the tlag for zero NE UNTIL, \ loop until it's not zero 4 (UP) RP MOV, \ restore local Return stack pointer so I can retrieve IP and SP RP *+ IP MOV, \ load this task's IP RP *+ SP MOV, \ load this task's SP NEXT, ENDCODE CODE UP! ( addr -- ) *SP+ UP MOV, NEXT, ENDCODE HEX 80 CONSTANT USIZE \ set to the size of FbForth USER area 80 CONSTANT USTACKS \ each task has 1/2 of this space. Could be smaller (#40 cells) -1 CONSTANT TRUE 0 CONSTANT FALSE : LOCAL ( PID uvar -- addr) ME - + ; \ usage: TASK1 RSAVE LOCAL @ : SLEEP ( task -- ) FALSE SWAP TFLAG LOCAL ! ; : WAKE ( task -- ) TRUE SWAP TFLAG LOCAL ! ; ( *** YOU M U S T call INIT-MULTI ONCE before multi-tasking ***) : INIT-MULTI ( -- ) USER0 UP! \ set my user-pointer register ME TLINK ! \ round robin links to ME TRUE TFLAG ! ; \ mark my task flag as AWAKE \ these words allow us to push values onto a local return stack : }RP-- ( task -- ) -2 SWAP RSAVE LOCAL +! ; \ make space on the local Rstack : }>R ( n task -- ) DUP }RP-- RSAVE LOCAL @ ! ; \ push n onto local Rstack ) HEX : FORK ( taskaddr -- ) >R \ taskaddr is the USER area for the new task R@ USIZE FF FILL \ erase user area USER0 R@ USIZE CMOVE \ copy USER0 vars to taskaddr R@ USTACKS + \ compute RETURN stack base address for this user area R@ RSAVE LOCAL ! \ store rstack base address in RSAVE of this new task \ add this task to round-robin list TLINK @ \ get copy of current user area (*saved by INIT-MULTI) R@ TLINK ! \ store this NEW taskaddr in curr. user's tlink R@ TLINK LOCAL ! \ now store curr. user into taskaddr's space R> SLEEP ; \ put the new task to sleep : ASSIGN ( XT task -- ) \ put stack address and XT onto local task's Rstack 2DUP JOB LOCAL ! DUP 58 + OVER }>R \ calc local SP base, push to rstack (Pstack is empty) DUP JOB LOCAL OVER }>R ; \ push addr of RUN onto local Rstack (goes into IP when task runs) INIT-MULTI ( setup the root task for mult-tasking) \ Syntax for setting up 2 tasks: \ ------------------------------ 0 VARIABLE TASK1 USIZE USTACKS + ALLOT 0 VARIABLE TASK2 USIZE USTACKS + ALLOT TASK1 FORK ( initialize the memory to be a user-area) TASK2 FORK VARIABLE X1 VARIABLE X2 : THING1 begin 1 X1 +! pause again ; \ code that needs to run in a task : THING2 begin -1 X2 +! pause again ; \ code that needs to run in a task T' THING1 TASK1 ASSIGN T' THING2 TASK2 ASSIGN TASK1 WAKE TASK2 WAKE Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 27, 2021 Share Posted April 27, 2021 Oops. This ran under the cross-compiler. Replace T' with ' Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted April 27, 2021 Author Share Posted April 27, 2021 1 hour ago, TheBF said: fbForth multi-tasker (untested) . . . A few things to note for fbForth use: Use R for R@ (or define) @(UP) already defined (see table below) Register Indirect No: Name Indirect Indexed Auto-increment -------- -------- ------- -------------- 8: UP *UP @(UP) *UP+ 9: SP *SP @(SP) *SP+ 10: W *W @(W) *W+ 14: RP *RP @(RP) *RP+ 13: IP *IP @(IP) *IP+ 15: NEXT *NEXT @(NEXT) *NEXT+ n: Rn *Rn @(Rn) *Rn+ CODE only requires NEXT, to end a definition, though, I use ASM: \ <wordname> \ code mnemonics ... ;ASM for mnemonics and CODE: \ <wordname> \ machine code ... ;CODE for machine code, which does not use , to compile. I think there may also be some gotchas with the User Variable Table, especially, with regard to relative location of some system variables. I must check. ...lee 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 27, 2021 Share Posted April 27, 2021 When I started to use the 64column editor I realized mine worked differently so I looked at my 35 year old dot matrix listings. It made code testing and stack juggling testing easy to have the little interpreter window beneath the code available. FbForthTestWindow.mp4 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 28, 2021 Share Posted April 28, 2021 The context switch works! FORTH DEFINITIONS -1 CONSTANT TRUE 0 CONSTANT FALSE ASM: ME ( -- addr) \ orignal name was MYSElf. Already used in FigForth SP DECT, UP *SP MOV, NEXT, ASM: UP! ( addr -- ) *SP+ UP MOV, NEXT, ME CONSTANT USER0 \ USER0 is the primary Forth task \ add these user variables to FbFORTH HEX 6E USER RSAVE \ temp storage for RP register when we change tasks 70 USER TFLAG \ flag that indicates task is awake or asleep 72 USER TLINK \ link next task in the round-robin queue 74 USER JOB \ XT of the what the task is running. ( *** YOU M U S T call INIT-MULTI ONCE before multi-tasking ***) : INIT-MULTI ( -- ) USER0 UP! \ set my user-pointer register ME TLINK ! \ round robin links to ME TRUE TFLAG ! ; \ mark my task flag as AWAKE \ Coventional Forth Pause ASM: PAUSE ( -- ) \ this is the context switcher RP DECT, SP *RP MOV, RP DECT, IP *RP MOV, RP 6E @(UP) MOV, \ RP -> LOCAL RSAVE BEGIN, 72 @(UP) UP MOV, \ next task's UP -> UP 70 @(UP) R0 MOV, \ test the tlag for zero NE UNTIL, \ or try next task 6E @(UP) RP MOV, \ restore RP this task RP *+ IP MOV, \ pop this task's IP RP *+ SP MOV, \ pop this task's SP NEXT, 2 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.