+Lee Stewart Posted April 27, 2015 Share Posted April 27, 2015 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 Quote Link to comment Share on other sites More sharing options...
Gary from OPA Posted April 27, 2015 Share Posted April 27, 2015 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. 1 Quote Link to comment Share on other sites More sharing options...
RXB Posted April 27, 2015 Share Posted April 27, 2015 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 Quote Link to comment Share on other sites More sharing options...
RXB Posted April 27, 2015 Share Posted April 27, 2015 (edited) 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 April 27, 2015 by RXB Quote Link to comment Share on other sites More sharing options...
Willsy Posted April 27, 2015 Share Posted April 27, 2015 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. Quote Link to comment Share on other sites More sharing options...
RXB Posted April 27, 2015 Share Posted April 27, 2015 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. Quote Link to comment Share on other sites More sharing options...
Gary from OPA Posted April 27, 2015 Share Posted April 27, 2015 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 3 Quote Link to comment Share on other sites More sharing options...
Willsy Posted April 27, 2015 Share Posted April 27, 2015 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 Quote Link to comment Share on other sites More sharing options...
+mizapf Posted April 27, 2015 Share Posted April 27, 2015 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? Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted April 27, 2015 Share Posted April 27, 2015 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 Quote Link to comment Share on other sites More sharing options...
Gary from OPA Posted April 27, 2015 Share Posted April 27, 2015 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. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted April 27, 2015 Share Posted April 27, 2015 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 Quote Link to comment Share on other sites More sharing options...
Gary from OPA Posted April 27, 2015 Share Posted April 27, 2015 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. 2 Quote Link to comment Share on other sites More sharing options...
+mizapf Posted April 27, 2015 Share Posted April 27, 2015 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. Quote Link to comment Share on other sites More sharing options...
Gary from OPA Posted April 27, 2015 Share Posted April 27, 2015 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. Quote Link to comment Share on other sites More sharing options...
RXB Posted April 28, 2015 Share Posted April 28, 2015 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 Quote Link to comment Share on other sites More sharing options...
Gary from OPA Posted April 29, 2015 Share Posted April 29, 2015 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. Quote Link to comment Share on other sites More sharing options...
RXB Posted April 29, 2015 Share Posted April 29, 2015 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. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted April 29, 2015 Share Posted April 29, 2015 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 Quote Link to comment Share on other sites More sharing options...
Tursi Posted April 29, 2015 Share Posted April 29, 2015 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. 3 Quote Link to comment Share on other sites More sharing options...
RXB Posted April 29, 2015 Share Posted April 29, 2015 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. Quote Link to comment Share on other sites More sharing options...
Tursi Posted April 29, 2015 Share Posted April 29, 2015 (edited) 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): 1076Timer: 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 April 29, 2015 by Tursi 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.