Jump to content

Lee Stewart

+AtariAge Subscriber
  • Posts

    5,844
  • Joined

  • Last visited

Everything posted by Lee Stewart

  1. Timing to run "7 ROLL" 10,000 times for different implementations of ROLL : Code Time (s) ---------------- -------- Forth 45 ALC recursive 9 ALC loop 3.5 ALC loop, bank#1 4.8 I expected the bank#1 code to take longer, but that looks like the way to go. ...lee
  2. All clever code aside, I will likely use high-level code for both PICK and ROLL because bank #0 is getting awfully cramped—or—I may loop out to other banks (requires only 8 bytes in bank #0), but I will need to check the speed hit first—not holding my breath. ...lee
  3. Ah! Well, I will change my comment to its not being possible in fbForth. Thanks. ...lee
  4. Yeah—that harness is stiff. I have taken the keyboard out; fixed the bad wire; re-assembled, only to break another wire. replacing that with a flexible cable is the only way to sanity! ...lee
  5. I don’t believe you actually used that code because it That code cannot possibly will not work in fbForth for two reasons*: MOVE copies cells, not bytes, so that code will underflow the stack. The source address for MOVE is below the destination address and the source and destination overlap, with the result that the TOS gets duplicated down the stack, overwriting everything in its path. ...lee __________________ * This does work in ANS Forth (see next post by @TheBF).
  6. Of course. I only used R7 because I thought it saved bytes, but, alas, it is actually worse because it takes the same space (8 bytes) with an extra instruction, so here it is as suggested: ROLL DATA $+2 MOV *SP+,R2 ;pop position (count) BL @ROLLIT ;do the ROLL ROLLEX B *NEXT ROLLIT *++ Push return address to return stack DECT R MOV R11,*R *++ 1- DEC R2 *++ IF JLT ROLITX ;we're done if negative *++ >R DECT R MOV *SP+,*R *++ MYSELF (recurse) BL @ROLLIT *++ SWAP R> (SWAP and pop return stack to under TOS) DECT SP MOV @2(SP),*SP ;over MOV *R+,@2(SP) ;under *++ Pop return address and return ROLITX MOV *R+,R11 RT ...lee
  7. OK...Here is an ALC recursion that works! It is 40 bytes, so 6 bytes longer than the simple loop, but it certainly is satisfying to accomplish it! ROLL DATA $+2 LI R7,ROLLIT ;load entry point for recursive call MOV *SP+,R2 ;pop position (count) BL *R7 ROLLEX B *NEXT ROLLIT *++ Push return address to return stack DECT R MOV R11,*R *++ 1- DEC R2 *++ IF JLT ROLITX ;we're done if negative *++ >R DECT R MOV *SP+,*R *++ MYSELF (recurse) BL *R7 *++ SWAP R> (pop return stack to stack and SWAP) DECT SP MOV @2(SP),*SP ;over MOV *R+,@2(SP) ;under *++ Pop return address and return ROLITX MOV *R+,R6 B *R6 Can it be refactored to tighter code? ...lee
  8. Continuing with this, PICK starts out just like ROLL , in that a similar ALC solution needs to get the address of the nth cell down from TOS, which allows for this code-sharing opportunity: ;[*** ROLL *** ( [n]..[0] +n --- [n-1]..[0][n] ) * DATA MROT_N * ROLL_N .NAME_FIELD 4, 'ROLL ' ROLL DATA $+2 BL @PIKROL ;get counter and nth cell pointer MOV R2,R2 ;counter=0? JEQ ROLLEX ;do nothing if flag=0 MOV R3,R4 ;save pointer DECT R4 ;point to (n-1)th cell MOV *R3,R0 ;save cell to move to TOS ROLLUP MOV *R4,*R3 ;copy down one cell DECT R3 ;next src cell DECT R4 ;next dst cell DEC R2 ;done? JNE ROLLUP ;nope..do another MOV R0,*SP ;yup..we're outta here ROLLEX B *NEXT ;[*++ PIKROL ++* called by PICK and ROLL PIKROL MOV *SP+,R2 ;position (count) ABS R2 ;force positive MOV R2,R3 ;save position SLA R3,1 ;correct to cell position A SP,R3 ;point to nth cell PKRLEX RT ;return with flag ;]* ;[*** PICK *** ( [n]..[0] +n --- [n-1]..[0][n] ) * DATA ROLL_N * PICK_N .NAME_FIELD 4, 'PICK ' PICK DATA $+2 BL @PIKROL ;get counter and nth cell pointer PICK01 DECT SP ;get room on stack MOV *R3,*SP ; PICKEX B *NEXT The BL..RT overhead adds 6 bytes to each word, but saves 10, for a net savings of 4 bytes for each word or 8 bytes total. Unfortunately, this forces an additional instruction to the code for ROLL , which results in saving only 2 bytes, and a net savings of only 6 bytes—perhaps not worth the somewhat convoluted code—though bank #0 space is getting very tight. I don’t know.... 🤔 ...lee
  9. Well, I think the reason the recursion works in the high-level code is that ROLL gets pushed to the return stack by DOCOL every time it is executed within itself and unrolls when the IF fails at n=0. I am unsure how I would manage that in the ALC. ...lee
  10. I am testing inclusion into the resident dictionary of fbForth 3.0 several convenient words that are currently defined in the FBLOCKS blocks file for optional use: CELLS 2DUP 2DROP 2SWAP NIP TUCK -ROT PICK ROLL WITHIN <> $. Most of them do not take much code. ROLL is an exception. If I use the high-level recursive Forth code (written by Marshall Linker) I have in FBLOCKS, it takes 22 bytes in bank #0, which has code only for code fields and parameter fields: : ROLL ( [n]..[0] +n --- [n-1]..[0][n] ) -DUP IF 1- SWAP >R MYSELF R> SWAP THEN ; Here is my ALC for ROLL , which takes 34 bytes. It does one thing that the above code does not and that is to disallow a negative n, so adding ABS before the -DUP to the above code makes this ALC just 10 bytes more. Perhaps I should check for stack underflow, which would take another 6 bytes—though none (or very few) of the other stack manipulation words do this, which puts the onus on the programmer: ROLL DATA $+2 MOV *SP+,R2 ;pop position (count) JEQ ROLLEX ;cannot be 0 JLT ROLLEX ;cannot be negative MOV R2,R3 ;save position SLA R3,1 ;correct to cell position A SP,R3 ;point to nth cell below TOS MOV *R3,R0 ;save cell to move to TOS MOV R3,R4 ;construct pointer to DECT R4 ; (n-1)th cell below TOS ROLLUP MOV *R4,*R3 ;copy down one cell DECT R3 ;next src cell DECT R4 ;next dst cell DEC R2 ;done? JNE ROLLUP ;nope..do another MOV R0,*SP ;yup..we're outta here ROLLEX B *NEXT If you see any way to tighten up this code, let me know. ...lee
  11. It does, indeed. Though for clarity, I would change the SWPB line to SWPB R0 ...lee
  12. As I mentioned in my last post, MAPAGX is irrelevant to any existing SAMS card. CRU bit 2 is not currently used. This was a design proposal by Thierry. ...lee
  13. I am pretty sure current SAMS cards do not use CRU bit 2 at >1E00. That was Thierry suggesting a possible design for a future card and how it might use that additional bit. We are only concerned with CRU bits 0 (disable[0]/(enable[1] access to mapper registers) and 1 (transparent[0]/mapping[1] mode). SAMS powers up in transparent mode with both CRU bits 0 and 1 off. To map SAMS pages, only CRU bit 0 needs to be on, but for the mapping to take effect, CRU bit 1 must be on. If you want the initial mapping to be the same as transparent mode (page 2 mapped to >2000, page 3 to >3000, page >A to >A000, ...), you should not need to do anything but turn CRU bit 1 on and leave it on and then manage mapping by sequences (per @TheBF above) of SBO 0 turn card on to access mapper registers * nn must be one of >04, >06, >14, >16, >18, >1A, >1C, >1E and R0 must be in LSB..MSB order MOV R0,@40nn map whatever SAMS page is in R0 to RAM address >1000*(nn)/2 SBZ 0 turn card off so other cards can access >4000..>5FFF It is important to turn the SAMS card off immediately after setting one or more mapper registers so other cards in the >4000..>5FFF space can be accessed. ...lee
  14. If it operates at all like other operating systems, I would guess it keeps an “age” list of empty clusters such that the most recent deletions go to the end of that list so that overuse is minimized. As to the actual algorithm, others will know better than I. @InsaneMultitasker? @9640News? @jedimatt42? @Ksarul? @mizapf? @F.G. Kaal? @Tursi? ...? ...lee
  15. I guess the problem some of us are having understanding your fixation on starting at the top and insisting that the cursor line move down is that, once the cursor gets to the bottom of the screen, precisely the same thing happens in both scenarios, the screen scrolls up with the cursor always on the new bottom line. If it is your wish to tweak XB and/or TI Basic so the command line operates like other Basic systems of your acquaintance, that cannot be done. If you want to treat the screen like a form on which everything fits with no scrolling, then using XB’s DISPLAY AT is, indeed, your friend. It is a bit more challenging with TI Basic, but doable, as @HOME AUTOMATION has shown. Of course, you could dig into one of the TI-99/4A implementations of Forth: TI Forth, TurboForth, fbForth, CAMEL99 Forth (see the TI-99/4A development resources thread for these and a host of other options. You can clear the screen and place the command cursor wherever you like—but, of course, they are not Basic. ...lee
  16. Yeah, I am sure there is a better solution. Anyway, I just edited the header, but, obviously did something wrong. One way to manage it would be to read the file into a 6144-byte block of VRAM and write it back out to a new file in DF128 format. Here are two of them: GPL Interface Specification for the 99_4 Disk Peripheral V2.0 03-28-1983.pdf File Management Specification for TI 99_4 Personal Computer V2.5 02-25-1983.pdf ...lee
  17. @Vorticon, try opening this as a DF128 file: VIGER1_PDF I converted this per @9640News’s suggestion. ...lee
  18. That is a PROGRAM type file (as indicated by @mizapf) with no record length. As @Gary from OPA said, you would need to read it a sector at a time with a DSR Level 2 subprogram >014 or all at once into VRAM with a Level 3 LOAD (XB’s OLD command uses this routine), which for your file would require 6144 bytes of VRAM. You cannot use OLD for a data file like yours and attempting it with ALC is probably not practical unless you can find that much VRAM. You can use subprogram >014 after setting up a 2-byte PAB in VRAM and about 25 bytes in scratchpad RAM (part at FAC) for subprogram-required information. You would use DSRLNK as BLWP @DSRLNK DATA 10 so would require an ALC routine to implement. I am not sure how you would invoke XB’s DSRLNK, but you could write your own. ...lee
  19. Unless you invoke the “strict” option ‘-s’ for E/A compatibility, you must separate comments from code by a minimum of 2 spaces because xas99 allows spaces between operands and operand components. In your case, xas99 thinks you want to multiply SCRWID by “24 NUMBER OF SPACES TO CLEAR” because only single spaces separate items following ‘24’. ...lee
  20. <pedantry> Not that anyone here but me cares, but the complements under discussion are properly labeled as “two’s complement” or “2’s complement” and “ones’ complement” or “1s’ complement”. The placement of the apostrophe indicates the plurality of the operation. Only a single ‘2’ is involved in computing the two’s complement (a single subtraction from 216 for our 16-bit machine, effected internally in the CPU as an inversion followed by adding 1), 1|0000 0000 0000 0000 - 0|0000 0000 0001 0011 ---|------------------- = 0|1111 1111 1110 1101 but many more than a single ‘1’ are involved in computing the ones’ complement (each bit is toggled). </pedantry> ...lee
  21. The two’s complement of 19 is, in fact, -19. With your ALC, you are dealing with words, so 19 = 0000 0000 0001 0011. The ones’ complement is 1111 1111 1110 1100 (-20) and the two’s complement is 1111 1111 1110 1101 (-19). You can reduce your two instructions to simply one NEG, which saves an instruction. If you are needing just the right byte (LSB), you can mask off the MSB, making your code .RELFUNC TWOCOMP,1 MOV *R10+,R1 ;GET FUNCTION ARGUMENT NEG R1 ;DO 2'S COMPLEMENT CONVERSION ANDI R1,>00FF ;mask off MSB MOV R1,*R10 ;PLACE RESULT ON STACK B *R11 .END ...lee
  22. Still working on the TODO list for fbForth 3.0, but here is the current list with not very many items left! Of the items left to do, I want to work on a couple before committing to them: fbForth300_TODO.txt The new DSRLNK currently being discussed in its own AA thread, FONTED full-font display screen toggles, Including UDSQRT in the resident dictionary—plenty of room for it and could use it for actual distances instead of their squares in coincidence calculations. Only hesitation is that the result is truncated instead of rounded, which likely does not matter. The recent tasks accomplished are Replacement of all SYSTEM calls with direct B or BL calls, with concomitant removal of the SYSTEM word and the its call table. Removal of many instances of “LIMI 0” due to (1) and addition of same to individual routines. Changing the user variable SCRFNT from a bi-state into a tri-state flag: (=0) default font from bank #3 of cartridge, (<0) user font file, (>0) console font with small caps for lowercase. ...lee
  23. $ is an assembly-time placeholder and represents the current program location wherever it is referenced in the program. It is not evaluated at run-time. And what @apersson850 said. This code will generate object code identical to my previous offering: STWP R1 MOV R1,@NEWWP+2 ; set up new WS LWPI MYWS ; Your code ; Time to return NEWWP LWPI >0000 ; load new WS ; more code ...lee
  24. No—well, partly. LWPI is a 2-word instruction. NEWWP points 1 word (2 bytes) past LWPI to the location of the >0000 word. The >0000 is overwritten with the new WS location. Oh, and I should add that the “LWPI MYWS” is not involved with the “MOV R1,@NEWWP”. Rather, it is copying the old WP to NEWWP so that a proper return to the old WS can be made without the programmer needing to know where it is. Perhaps, it should have been named OLDWP. ...lee
×
×
  • Create New...