Jump to content
IGNORED

Internal GPL Interpreter?


Retrospect

Recommended Posts

Not a problem, since the 9918 also has an autoincrement reading, maybe its time for refresh'ing course, this one is good read:

 

http://spatula-city.org/~im14u2c/vdp-99xx/e3/1980_Arizona_Technical_Symposium_Draft.pdf

 

And if you scroll down to page 14 you will see from TI Guru himself 'Karl' that he mentions right there how well the VRAM can be used by the interpreter.

 

In fact TI BASIC does that also, auto reading each byte out of VRAM to decode the opcode bytes of your BASIC program.

 

That does not answer my questions at all. I am well aware that the VDP is autoincrementing as are GROMs. I am also well aware that the GPL interpreter has no trouble reading VRAM (or writing, for that matter). What the GPL interpreter does not do is interpret GPL byte code from anywhere but GROM/GRAM unless it can be fooled, which was the point of my questions. It would be easy enough to read the next, autoincremented byte from VRAM; but, how can the interpreter be made to branch to or call an address when VRAM addresses are written with the LSB first, which is backwards from how GROM/GRAM addresses are written (with the MSB first)?

 

...lee

Link to comment
Share on other sites

That does not answer my questions at all. I am well aware that the VDP is autoincrementing as are GROMs. I am also well aware that the GPL interpreter has no trouble reading VRAM (or writing, for that matter). What the GPL interpreter does not do is interpret GPL byte code from anywhere but GROM/GRAM unless it can be fooled, which was the point of my questions. It would be easy enough to read the next, autoincremented byte from VRAM; but, how can the interpreter be made to branch to or call an address when VRAM addresses are written with the LSB first, which is backwards from how GROM/GRAM addresses are written (with the MSB first)?

 

...lee

Ok, yeah it not perfect, if you using the actual internal console rom interpreter, you have to load up the first GPL address backwards, so you get the right starting point in VRAM to fetching code from.

 

The second problem is in your Branch statements you have to swap the address bytes by hand after assembling your code, personally I never done it running GPL code out of VRAM, I see it only useful for short pieces of code you load there and GPLLNK to, not for running whole module codes, as GPL opcodes that also reading/writing to VDP RAM for screen/table operations I would see it fucking up where to keep reading next opcodes from.

 

The easy way is to code up a very small assembly code that does the fetching, but if you going to do that you might as well do like the linker and just run the code from 32k assembly space instead, using a new coded GPL interpreter, which is very small under 2k to do all the work, branching to console rom parts that you don't need to edit or modified.

  • Like 1
Link to comment
Share on other sites

 

Great!—but, that is not running GPL byte code from VRAM. You said you do it “by some small memory tricks”. Could you explain how you do this? Do you change a GPL workspace register to point to VRAM for the next GPL byte? Given that writing a VRAM address starts with the LSB and writing a GROM/GRAM address starts with the MSB, how do you pass the VRAM address to the GPL interpreter for the next GPL byte when that byte is not the one ready for reading after autoincrement from the previous read?

 

...lee

Sadly when I did this many years ago it was on my SCSI hard drive that failed.

I used a routine I borrowed from GRAMDISK and demoed it as a VDPDISK / GRAMDISK / RAMDISK that would run from VDP or GRAM.

I used these in the Demo for RXB version 5.55 at a USA faire.

 

Anyway here is the GPL code for controlling the SAMS from GPL:

***********************************************************
* RXB
*******************************************************
AMAP   DATA APAS
       DATA AMSMAP
       STRI 'AMSMAP'          CALL AMSMAP
AMSMAP OR   >08,@FLAG
       DADD 7,@TKNPT
       CALL AMSM
       BR   AMSSVD
AMSM   CALL AMSSUB
       DST  >1D01,@>8314
       XML  >F0
       RTN
APAS   DATA AOFF
       DATA AMSPAS
       STRI 'AMSPASS'         CALL AMSPASS
AMSPAS OR   >08,@FLAG
       DADD 8,@TKNPT
       CALL AMSP
       BR   AMSSVD
AMSP   CALL AMSSUB
       DST  >1E01,@>8314
       XML  >F0
       RTN
AOFF   DATA AON
       DATA AMSOFF
       STRI 'AMSOFF'          CALL AMSOFF
AMSOFF OR   >08,@FLAG
       DADD 7,@TKNPT
       CALL AMSF
       BR   AMSSVD
AMSF   CALL AMSSUB
       DST  >1E00,@>8314
       XML  >F0
       RTN
AON    DATA AINIT
       DATA AMSON
       STRI 'AMSON'           CALL AMSON
AMSON  OR   >08,@FLAG
       DADD 6,@TKNPT
       CALL AMSO
       BR   AMSSVD
AMSO   CALL AMSSUB
       DST  >1D00,@>8314
       XML  >F0
       RTN
AINIT  DATA ABANK
       DATA AMSINT
       STRI 'AMSINIT'         CALL AMSINIT
AMSINT OR   >08,@FLAG
       DADD 8,@TKNPT
       CALL AMSO
       DST  >5FFE,@FAC
       ST   >0F,@FAC2
AINITL MOVE 1,@FAC2,@0(@FAC)
       DDECT @FAC
       DEC  @FAC2
       BR   AINITL
       CALL AMSF
       CALL AMSM
AMSSVD CALL AMSRST
       BR   G6DED
******************************
AMSSUB MOVE 24,@>8300,V@>03C0
       MOVE 24,G@AMSCRU,@>8300
       RTN
AMSRST MOVE 24,V@>03C0,@>8300
       RTN
******************************************************
* CPU PROGRAM FOR >8300 SCATCH PAD SUBROUTINE AMSCPU *
***********************************************************
*                 *        AORG >8300
AMSCRU DATA >8302 * CPUPGM DATA >8302      * First address.
       DATA >0420 *        BLWP @AMSCPU    * Switch contex
       DATA >830C *
       DATA >04E0 *        CLR  @>837C     * Clear for GPL
       DATA >837C *
       DATA >045B *        RT              * Return to GPL.
******************************************************
*                 * AMS CPU SUBPROGRAM
       DATA >834A * AMSCPU DATA >834A
       DATA >8310 *        DATA AMSCRU
       DATA >020C * AMSCRU LI   R12,>1E00
       DATA >1E00 *
       DATA >1D00 *        SBO  0
       DATA >0380 *        RTWP
***********************************************************
*                 *        END
******************************************************
ABANK  DATA ION
       DATA AMSBNK
       STRI 'AMSBANK'         CALL AMSBANK(bank-number)
AMSBNK CALL SNAME
       PARS >B6
       CEQ  >65,@FAC2
       BS   G6F0C
       XML  CFI             GET MEMORY NUMBER 0-F
       CEQ  >03,@FAC10
       BS   G6F07
       DCHE 16,@FAC
       BS   G6F07           NUMBER TO BIG ERROR
       SLL  1,@FAC1         TIME 2
       ST   @FAC1,@>8304    SAVE MEMORY NUMBER
       CEQ  >B3,@XTOKN
       BR   G6DE8
       XML  GBYTE
       PARS >B6
       CEQ  >65,@>FAC2
       BS   G6F0C
       XML  CFI              GET BANK NUMER
       CEQ  >03,@FAC10
       BS   G6F07
       DCHE 256,@FAC
       BS   G6F07            NUMBER TO BIG ERROR
       ST   @FAC1,@>8305     SAVE BANK NUMBER
       CALL AMSM              * AMSMAP
       CALL AMSO              * AMSON
       DCLR @FAC                CLEAR FOR INDEX
       ST   @>8304,@FAC1        MEMORY ADDRESS FOR INDEX
       ST   @>8305,@>4000(@FAC) LOAD BANK PAGE FOR MEMORY
       CALL AMSF              * AMSOFF
       B    G6DE8
*******************************
AMSERR ST   @FAC,@>4004       * Restore old page.
       ST   @FAC1,@>4006      * Restore old page 2.
       CALL AMSF              * AMSOFF
       CALL BADTON
       MOVE 736,V@32,V@0
       FMT
       SCRO >60
       ROW  23
       COL  2
       HTEX '* WARNING AMS BANK ERROR *'
       FEND
       BR   G6F11
******************************************************
ION    DATA IOFF
       DATA ISRON
       STRI 'ISRON'           CALL ISRON(variable)
ISRON  CALL SNAME
       PARS >B6
       CEQ  >65,@FLAG
       BS   G6F0C                * STRING NUM MISMACTH
       XML  CFI
       CEQ  >03,@FAC2
       BS   G6F07                * NUM TO BIG
       DCZ  @FAC
       BS   G6F02                * BAD VALUE
       MOVE 26,@8300,V@>03C0
       MOVE 14,G@GISRON,@>8300
       XML  >F0
       CALL SISRLD
       BR   G6DE8
SISRLD MOVE 26,V@>03C0,@>8300
       RTN
******************************************************
* CPU PROGRAM FOR >8300 SCRATCH PAD CPU ISR HOOK ON  *
******************************************************
*                  *        AORG >8300
GISRON DATA >8302  *        DATA >8302
       DATA >C820  *        MOV  @>834A,@>83C4
       DATA >834A  *
       DATA >83C4  *
       DATA >04E0  * EXIT   CLR  @>837C
       DATA >837C  *
       DATA >045B  *        RT
*                  *        END
******************************************************
IOFF   DATA >0000
       DATA ISROFF
       STRI 'ISROFF'          CALL ISROFF(variable)
ISROFF DST  @>83C4,@>8304     SAVE ISR HOOK
       MOVE 26,@>8300,V@>03C0
       MOVE 26,G@GISROF,@>8300
       XML  >F0
       CALL SISRLD
       CALL SNAME
       PARS >B6
       CEQ  >65,@XTOKN
       BS   G6F0C             STRING NUM MISMATCH
       XML  LUNAM             GET SYMBOL ADDRESS
       XML  VSENT             GET SYMBOL VALUE
       XML  VPUSH             PUSH ON STACK
       DST  @>8304,@FAC       GET SAVED ISR HOOK
       XML  ASVAL             ASSIGN VARABLE
       BR   G6DE8
******************************************************
* CPU PROGRAM FOR >8300 SCRATCH PAD CPU ISR HOOK OFF *
******************************************************
*                          AORG >8300
GISROF DATA >8302 *        DATA >8302
       DATA >C820 * ISROFF MOV  @>83C4,@>83C4
       DATA >83C4 *
       DATA >83C4 *
       DATA >1305 *        JEQ  NHOOK
       DATA >C820 *        MOV  @>83C4,@>834A
       DATA >83C4 *
       DATA >834A *
       DATA >04E0 * NHOOK  CLR  @>83C4
       DATA >83C4 *
       DATA >04E0 *        CLR  @>837C
       DATA >837C *
       DATA >045B *        RT
*                 *        END
**************************************************************************
       END
 
 

Link to comment
Share on other sites

Not a problem, since the 9918 also has an autoincrement reading, maybe its time for refresh'ing course, this one is good read:

 

http://spatula-city.org/~im14u2c/vdp-99xx/e3/1980_Arizona_Technical_Symposium_Draft.pdf

 

And if you scroll down to page 14 you will see from TI Guru himself 'Karl' that he mentions right there how well the VRAM can be used by the interpreter.

 

In fact TI BASIC does that also, auto reading each byte out of VRAM to decode the opcode bytes of your BASIC program.

Thanks Gary for helping me explain it.

 

I only had a dinky demo and got some help from Assembly programmers on the phone helped with some of the code.

 

It did not do much to be impressed with just read VDP off screen and showed where it was running from in VDP. It was really really slow.

Edited by RXB
Link to comment
Share on other sites

Ok, yeah it not perfect, if you using the actual internal console rom interpreter, you have to load up the first GPL address backwards, so you get the right starting point in VRAM to fetching code from.

 

The second problem is in your Branch statements you have to swap the address bytes by hand after assembling your code, personally I never done it running GPL code out of VRAM, I see it only useful for short pieces of code you load there and GPLLNK to, not for running whole module codes, as GPL opcodes that also reading/writing to VDP RAM for screen/table operations I would see it fucking up where to keep reading next opcodes from.

 

The easy way is to code up a very small assembly code that does the fetching, but if you going to do that you might as well do like the linker and just run the code from 32k assembly space instead, using a new coded GPL interpreter, which is very small under 2k to do all the work, branching to console rom parts that you don't need to edit or modified.

That's still not s complete explanation in my book. Fact is, to read and write to GROM/GRAM requires a read our write to two memory addresses in the 4A memory map. Reading and writing VDP requires to *different* memory addresses. You can load addresses backwards all day long, the interpreter will still send those those addresses to the *GROM* ports, not VDP.

 

So, unless some explicit mechanism has been coded into the GPL interpreter by design, I say it can't be done. I just can't see how it's possible.

Link to comment
Share on other sites

That's still not s complete explanation in my book. Fact is, to read and write to GROM/GRAM requires a read our write to two memory addresses in the 4A memory map. Reading and writing VDP requires to *different* memory addresses. You can load addresses backwards all day long, the interpreter will still send those those addresses to the *GROM* ports, not VDP.

 

So, unless some explicit mechanism has been coded into the GPL interpreter by design, I say it can't be done. I just can't see how it's possible.

Yea to change this would require all of GPL GROM 0 to be changed to VDP addresses and a few ROM 0 routines would also have to be changed.

 

Running GPL from RAM would be much more easy.

Link to comment
Share on other sites

That's still not s complete explanation in my book. Fact is, to read and write to GROM/GRAM requires a read our write to two memory addresses in the 4A memory map. Reading and writing VDP requires to *different* memory addresses. You can load addresses backwards all day long, the interpreter will still send those those addresses to the *GROM* ports, not VDP.

 

So, unless some explicit mechanism has been coded into the GPL interpreter by design, I say it can't be done. I just can't see how it's possible.

The console rom on boot-up setups GPL workspace registers, and it uses R13 and R15 to control what memory map it uses to read/write GROM (R13) and read/write VDP (R15). (Base is at >83E0)

 

You change those two values in your own code either via power-up in >6000 or DSR >4000 or in 32K, and the console rom never checks again to see if R13/R15 is right it assumes they should still mapped to the right devices.

 

The first step in getting GPL to run out of VDP is to change to LWPI >83E0 workspace, setup R13 to be the VDP Memory Map port of >8800 instead of normal >9800, setup the other two needed registers R14 to >0100 and R15 to normal VDP write address >8C02 and then jump into the start of the GPL Int. with R0 setup with where your GPL code has been already loaded in VRAM with of course the starting point address backwards. So if you placed your VRAM GPL code at >2000 you would setup R0 with >0020.

 

The neat thing is default start address of GPL in GROM 0 is >0020. So putting GPL code at >2000 in VRAM is perfect place all you would have to do is change R13 to >8800 and then branch to entry >0028 in the console rom which is one line after the R13 setup and the rest of power-up is done normally, setuping up the rest of registers and it would end up excuteing the first byte of GPL code from >2000 in VRAM instead of >0020 in GROM 0.

 

Attached below is some of console rom source code from me up until the kscan, you can follow it and see how the boot-up is setup and how it fetchs the opcodes to decide on from, which is all memory map by R13, so changing that changes everything else basically. -- In Theory the way console rom is designed you could even have multiple VDP's mapped at other locations, and change R15 to have GPL throw everything up to another screen! :)

 

ConsoleSourceExample.txt

 

Hope this helps you to understand more. Maybe I should write-up a demo example of code running from VDP RAM and then post it, but being end of month tax time I am very busy, so hope this is enough and you can figure out the rest, but I will be here online often, so just ask more questions and I will do my best to answer them. Thanks

  • Like 3
Link to comment
Share on other sites

The console rom on boot-up setups GPL workspace registers, and it uses R13 and R15 to control what memory map it uses to read/write GROM (R13) and read/write VDP (R15). (Base is at >83E0)

 

You change those two values in your own code either via power-up in >6000 or DSR >4000 or in 32K, and the console rom never checks again to see if R13/R15 is right it assumes they should still mapped to the right devices.

Aha! Now that makes sense.

 

Yes a demo of this (and a YouTube video if possible - to show the code writing/compiling process) would be very cool!

 

Thanks Gary & Rich

Link to comment
Share on other sites

One thing left, though:

 

 

PUSH actual GROM address on subroutine stack
0864 05E0 INCT @>8373    Increase stack pointer
0866 8373
0868 D120 MOVB @>8373,4
086A 8373
086C 0984 SRL 4,8
086E D92D MOVB @>0002(13),@>8300(4)   Address GROM on stack
0870 0002
0872 8300
0874 D92D MOVB @>0002(13),@>8301(4)
0876 0002
0878 8301
087A 0624 DEC @>8300(4) Correct address
087C 8300
087E 045B B  *11  Return

 

... taken from TI Intern, documenting a part of the GPL interpreter.

 

If you set R13 to 8800, line 0874 will do a read from 8802, which is the VDP status register. Wouldn't that be a problem?

Link to comment
Share on other sites

One thing left, though:

...

... taken from TI Intern, documenting a part of the GPL interpreter.

 

If you set R13 to 8800, line 0874 will do a read from 8802, which is the VDP status register. Wouldn't that be a problem?

 

 

If that is not a show-stopper, there is also the problem of restoring GPLWS R13 every time you want to call or branch to a console GROM routine and back when you return.

 

...lee

Link to comment
Share on other sites

One thing left, though:

 

 

PUSH actual GROM address on subroutine stack
0864 05E0 INCT @>8373    Increase stack pointer
0866 8373
0868 D120 MOVB @>8373,4
086A 8373
086C 0984 SRL 4,8
086E D92D MOVB @>0002(13),@>8300(4)   Address GROM on stack
0870 0002
0872 8300
0874 D92D MOVB @>0002(13),@>8301(4)
0876 0002
0878 8301
087A 0624 DEC @>8300(4) Correct address
087C 8300
087E 045B B  *11  Return

... taken from TI Intern, documenting a part of the GPL interpreter.

 

If you set R13 to 8800, line 0874 will do a read from 8802, which is the VDP status register. Wouldn't that be a problem?

 

Here is what the assembled commented source code looks like for that section:

 

***************************************
* RETURN ADR. FROM LIBRARY OR PROGRAM *
***************************************
RGBA   BL   @GETSTK           RECALL GROM BASE ADR.
       MOV  @PAD(R4),R13
       MOVB R4,@GWDOFF(R13)   SYNC THE GROMS
 
RETURN SZCB @HX20,@STATUS     RESET CONDITION BIT
 
RETNC  LI   R11,NEXT
 
GETSTK MOVB @STKADD,R4        LOAD ADR. OF SUBROUTINE STACK
       SRL  R4,8              MOVE TO LSB
GTSTK  DECT @STKADD           NEW VALUE OF STACK POINTER
GTSTK1 MOVB @PAD(R4),@GWAOFF(R13)           LOAD RTN ADR.
       MOVB @PAD+1(R4),@GWAOFF(R13)
       RT
 
************************************
* PUSH PGM COUNTER IN K ONTO STACK *
************************************
CALL   MOVB *R13,R6           GET BRANCH ADR FROM GROM
       LI   R11,LDKADD        SET RTN POINTER
       MOVB *R13,@R6LSB
 
PUTSTK INCT @STKADD           NEW VALUE OF STACK POINTER
       MOVB @STKADD,R4        LOAD ADR. OF STACK
       SRL  R4,8              TO LSB
       MOVB @GRAOFF(R13),@PAD(R4)           SAVE ADR ON STACK
       MOVB @GRAOFF(R13),@PAD+1(R4)
       DEC  @PAD(R4)
       RT
Yes it would be problem, if you GPL code is bouncing around to other sections of GPL code from within VRAM.

 

Running GPL from VRAM is only useful for one-shot run of code, with no multiple branch/with/returns or calls to other sections of codes.

 

If you want to do anymore, then you have to rewrite the GPL Interpreter itself and change it around, and if you doing that might as well do it for 32k like others have already, as the actual changes are small and so is the GPL Interpreter, surprising enough it not very big. Most of the console rom is to handle the Floating Point Math, TI BASIC opcodes that GPL is calling out, and the sprite motion and keyboard scan.

Link to comment
Share on other sites

I am having real difficulty seeing how it could be useful at all. If any of this “one-shot” VRAM-resident GPL touches VRAM through R15, it is off into the weeds for the next instruction.

 

...lee

Yeah, if any of GPL opcodes are trying to also update VDP like for screen output the whole thing would go crazy.

 

The limit of code you could branch to from this trick which would have to be all setup anyway from normal assembly space would not save much in what you could just do directly. It might be only useful I can see in some weird way to on purpose hide the point of your code, it would make for some neat copy protection i think it would take someone alot to figure it out from just plain disassembly, but these days not much point in that.

  • Like 2
Link to comment
Share on other sites

Yes it would be problem, if you GPL code is bouncing around to other sections of GPL code from within VRAM.

Running GPL from VRAM is only useful for one-shot run of code, with no multiple branch/with/returns or calls to other sections of codes.

 

OK, now this is fully agreed.

 

The suggestion to set GPLRD from 9800 to 8800 sounded somewhat like a full replacement for GROMs, which should not be feasible. However, for simple structures without branching this should indeed work.

Link to comment
Share on other sites

OK, now this is fully agreed.

 

The suggestion to set GPLRD from 9800 to 8800 sounded somewhat like a full replacement for GROMs, which should not be feasible. However, for simple structures without branching this should indeed work.

Personally I would love to see a wholly new replacement console ROM written that has redesigned better GPL interpreter and other functions.

 

I myself did a good replacement of GROM 0 OS and enhanced it with SOB, but the next step in re-assembling from licensed source a new ROM that is backwards compatible but let offers more options to the user directly like running GPL from any type of memory, and direct support for newer hardware would be much welcome.

 

Of course for use on a TI99 motherboard, a hardware board designed to replace the console roms with flashable rom would be needed, but I think if there is good new OS written it would be worth it to follow up with the hardware to support it.

 

Someday, hopefully in sooner then later future it will happen.

Link to comment
Share on other sites

Or using a Ultra SAMS with 10 Meg of memory.

 

>6000 to >FFFF for loading 32K at a time, >2000 to >4FFF for Device Support and Assembly support.

 

It would even be possible to load alternate >0000 to >1FFF

Link to comment
Share on other sites

All this chatter about running GPL from VDP RAM, got me remembering the fact that the other interpreter found stock in all TI99's the TI BASIC one is designed from ground-up to infact look and fetch its opcodes from either VDPRAM or GROM memory.

 

In theory you could have 5x8K TI BASIC program, and using ubergrom even much more. -- This is one feature even TI used a few times some of their modules they infact were loading a BASIC program from GROM, with added CALL's written in GPL, instead of writing the whole program in GPL.

 

It just too bad the whole setup is slow, read from GROM as BASIC it then in turn has to get interpreter by GPL code from GROM which in turn gets interpreter by Assembly in console rom. -- What a waste of cycles.

Link to comment
Share on other sites

All this chatter about running GPL from VDP RAM, got me remembering the fact that the other interpreter found stock in all TI99's the TI BASIC one is designed from ground-up to infact look and fetch its opcodes from either VDPRAM or GROM memory.

 

In theory you could have 5x8K TI BASIC program, and using ubergrom even much more. -- This is one feature even TI used a few times some of their modules they infact were loading a BASIC program from GROM, with added CALL's written in GPL, instead of writing the whole program in GPL.

 

It just too bad the whole setup is slow, read from GROM as BASIC it then in turn has to get interpreter by GPL code from GROM which in turn gets interpreter by Assembly in console rom. -- What a waste of cycles.

This could be speeded up if you run the GPL from RAM instead of GROM, so using the Simulated GPL routine running from RAM could load from VDP RAM much faster, but not much.

 

Still think a pure GPL program running from RAM and it fetches those programs from GROM would be kind of cool. Using GROM would save RAM and running from RAM would be fast like C or Forth.

Link to comment
Share on other sites

This could be speeded up if you run the GPL from RAM instead of GROM, so using the Simulated GPL routine running from RAM could load from VDP RAM much faster, but not much.

 

Still think a pure GPL program running from RAM and it fetches those programs from GROM would be kind of cool. Using GROM would save RAM and running from RAM would be fast like C or Forth.

 

I'm not sure that's right, Rich. The GPL interpreter in console ROM is on a 16-bit bus. A simulator in CPU RAM is on an 8-bit bus. Of course, I don't know about the relative speeds of walking the GPL byte code in GROM vs. RAM; but, the console interpreter would definitely run its own ALC faster.

 

...lee

Link to comment
Share on other sites

I recently found my notes wherein I measured the read speed of GROMs (I was testing against the AVR GROM code I wrote). Running the AVR at 20MHz with an external clock, single reads were taking roughly 5 wait states to execute (just slightly slower than 8-bit RAM at 4 wait states). A normal GROM read takes over 25 wait states. Even with the 5:1 speed advantage on GROMs, a GPL program like TI BASIC has no visible speed improvement (yes, I removed all real GROMs from the system to run the test). (The 8MHz AVR [internal clock] takes about 14 wait states - still markedly faster). The point is that the GPL interpreter spends a lot more time reading CPU ROM than it does reading GROM, enough that a 5 times faster GROM chip is only marginally faster in practice. it doesn't take much time looking at TI Intern to see this is true -- count the CPU cycles between two GPL instructions, you'll see that it easily absorbs the slower speed of the GROM chip itself.

  • Like 3
Link to comment
Share on other sites

I recently found my notes wherein I measured the read speed of GROMs (I was testing against the AVR GROM code I wrote). Running the AVR at 20MHz with an external clock, single reads were taking roughly 5 wait states to execute (just slightly slower than 8-bit RAM at 4 wait states). A normal GROM read takes over 25 wait states. Even with the 5:1 speed advantage on GROMs, a GPL program like TI BASIC has no visible speed improvement (yes, I removed all real GROMs from the system to run the test). (The 8MHz AVR [internal clock] takes about 14 wait states - still markedly faster). The point is that the GPL interpreter spends a lot more time reading CPU ROM than it does reading GROM, enough that a 5 times faster GROM chip is only marginally faster in practice. it doesn't take much time looking at TI Intern to see this is true -- count the CPU cycles between two GPL instructions, you'll see that it easily absorbs the slower speed of the GROM chip itself.

Hmmm the bigger the program the better the speed increase would be seen right?

 

By the way TI Basic unlike GPL is DOUBLE INTERPRETED so Assembly fetches GPL then GPL fetches TI Basic commands.

I thought we were talking about only GPL not TI BASIC which requires an addition read to a program.

Link to comment
Share on other sites

Your point is valid, Rich, but the faster interpreter should still have sped up the double-interpretation (although, as you suggest, diminishing returns). :) But even the rest of GPL didn't feel much snappier - title page, boot menu, Editor/Assembler, even the Demonstration cart - I tried a number of things.

 

I'm home now, the actual values I recorded using a logic analyzer, copying 6k of memory to scratchpad:

 

16-bit RAM: 58ms

8-bit RAM: 65ms (roughly 4 wait states, which is what we'd expect)

20MHz AVR GROM: 75ms (roughly 8 wait states per access)

8MHz AVR GROM: 88ms (roughly 14 wait states per access)

TI GROM: 113ms (roughly 26 wait states per access)

 

Note: I had noticed that when setting the address, the second byte holds up the system for much longer than a read, but I didn't record the durations I measured.

 

Not quite 5:1 like I remembered, but 3:1 on the fast AVR. This was the test that let me feel comfortable that the internal 8MHz AVR clock was fast enough, though. (Disclaimer: the 'UberGROM' is not measured, this was early code).

 

Nevertheless, the reason I looked into it was because I was surprised! Like most of us, I assumed the slow nature of the GROM access (which was reinforced by that measurement) was a factor in the speed of the interpreter, and having a faster "GROM" would make a visible difference.

 

If we actually look at a sample of GPL code, though, we can sort of get an idea what's going on. Here's a sample from Classic99 sitting on the master title page. Classic99 does NOT emulate the GROM speed - it treats it as normal memory from the standpoint of performance, so we'll add the delay time in manually.

 

Address CPU >0078 is the address where the interpreter fetches a new GPL instruction (data for the instruction is fetched elsewhere). I decided to measure a couple of instructions after you press a key, because these are simple instructions that don't need to fetch very much additional GROM data. In TI Intern, they live at G@>01B6 and are:

 

ST @>8372,>FE -- BE 72 FE

ST @>83D6,>06 -- BE 6D 06

CLR @>836C -- 86 6C

 

Three very simple instructions, with just 8 bytes of GROM data in use, no branches or anything to complicate things.

 

Timer: 736 CPU cycles - Min: 224 Max: 38890 Average(27426): 1076

Timer: 736 CPU cycles - Min: 224 Max: 38890 Average(27427): 1076
Timer: 570 CPU cycles - Min: 224 Max: 38890 Average(27428): 1076

 

To measure, I set up a timer breakpoint, excluding the active interrupt to prevent that from being included: T(0078-0070)

I then set a breakpoint to catch space bar: M8375=20

I pressed Space, and the emulator breakpointed. I deleted the spacebar breakpoint and added a breakpoint for 0078.

I continued execution, then each time it breakpointed, I stepped once and checked R9 (where the GROM byte was read). When it was >07, I knew I found the 'ALL >20' command. I simply ran three more times then captured the last three debug statements. I repeated a couple of times to make sure it was consistent.

 

So, we see that those three instructions took 736+736+570 CPU cycles, which is 2042 cycles. We know that Classic99 is not emulating the GROM speed, so it's treating that as regular, 4 wait state, 8-bit memory. The truth is more like 26 cycles, we learned above, and there are 8 GROM reads. (Since 4 cycles were accounted for, we'll multiply by 22 cycles). 8*22 is 176 cycles extra for those bytes from real GROM.

 

So this is what's really happening. The "real" runtime of those three instructions would be about 2218 CPU cycles. But the slow GROM only accounts for 176 of those cycles, which is less than 8% of the time. This means that a GROM chip that ran at the speed of RAM would only run GPL 8% faster, on simple instructions.

 

Instructions that accessed GROM more often (like perhaps MOVE from GROM) would benefit more, while instructions that access it less (like perhaps ALL) would see less benefit, but as an overall average you're probably lucky to get 10%. That's not /bad/, but it's not the win I expected to see. My AVR only gets a third of that, and 3% falls into the system's clock variance, it's lost in the noise. (+/-5% according to the datasheet for the clock generator, and I have consoles that measure at both ends ;) ).

 

In going through the GPL interpreter, you can tell it was written to be flexible and accommodate a lot of situations - it doesn't cache data, and it reloads GROM and VDP addresses far more often than it has to (MOVE is a huge culprit of this), and it branches around a LOT, maybe to save memory. Since alternate situations never happened, and ROM is cheap now, it should be possible IMO to write a much faster GPL interpreter that runs the same code. It's just something I'll probably never personally get to. :/

Edited by Tursi
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...