senior_falcon Posted August 7 Author Share Posted August 7 (edited) 7 hours ago, Lee Stewart said: What's keeping you from running the interpreter from cartridge ROM? ...lee In theory most, maybe even all, of the interpreter could be kept in the cartridge ROM, which would free up more memory for the BASIC program. But that's not how Stuart did it, and making a change like that is way beyond my abilities or interest level. This would work well with 4 grom banks and 1 rom bank, and of course, that would allow the v2.2 consoles to run it. Is there any reason why this approach would be less desirable than an all rom cartridge. Realistically, there isn't a lot of activity with Cortex BASIC, so the ability to make cartridges from non-existent programs is probably not all that useful. Is there another lossless compression method that can be used on the TI that produces more compact code than dan2? Edited August 7 by senior_falcon 2 Quote Link to comment Share on other sites More sharing options...
Tursi Posted August 7 Share Posted August 7 6 hours ago, senior_falcon said: Is there another lossless compression method that can be used on the TI that produces more compact code than dan2? I had unzip running in libti99, but it's not fast. vgmcomp can pack arbitrary binary streams - I used it for a number of projects that I moved to copy carts a few years ago (the original vgmcomp, not vgmcomp2). Couldn't say how well it packs relative to dan2, but since the underlying intent is different it's probably less dense. 3 Quote Link to comment Share on other sites More sharing options...
Stuart Posted August 7 Share Posted August 7 18 hours ago, Lee Stewart said: What's keeping you from running the interpreter from cartridge ROM? Running more of it from the cartridge would require a hefty rewrite to handle the bank switching, as well as a greater understanding of how the original code works. An awful lot of work for the maybe dozen or so people worldwide who might actually make use of it. 4 Quote Link to comment Share on other sites More sharing options...
+OLD CS1 Posted August 8 Share Posted August 8 1 hour ago, Stuart said: An awful lot of work for the maybe dozen or so people worldwide who might actually make use of it. Shame. I am rather attracted to this dialect of BASIC. It hauls ass and has simple commands for graphics like we saw for other 8-bits of the area (I always despised/envied HPLOT and VPLOT in AppleSoft BASIC.) Could have been a contender. Quote Link to comment Share on other sites More sharing options...
Reciprocating Bill Posted August 8 Share Posted August 8 It would be cool if just the floating point format and routines could be extracted and made available, to be called from an assembly program. 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 8 Share Posted August 8 52 minutes ago, Reciprocating Bill said: It would be cool if just the floating point format and routines could be extracted and made available, to be called from an assembly program. Or whatever else might want to call 'em. Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted August 8 Share Posted August 8 (edited) On 8/2/2023 at 10:45 PM, Lee Stewart said: According to this, the largest representable hex number is 0.FFFFFFFFFF16 x 1016+63 , which is ~7.237005610 x 1010+75. The actual precision claimed in another doc above is only 11 decimal digits. Considering that the hex mantissa above is 10 hex digits and that the decimal value (without considering the radix point) is 1099511627775 (which is 13 decimal digits), the possible, extra 2 digits must be swamped enough by rounding/calculation errors to disallow any better precision. ...lee I recognize this format from the TMS99000's floating point. It is an IBM/360 compatible, single-precision 32 bits. Cortex extends it to 48 bits. See Wikipedia, IBM Hexadecimal Floating Point. It has a shortcoming called "wobbling precision." The first digit, from 0001 to 1111, can have 3 leading zeroes. Even though Cortex' mantissa is 40 bits, its effective precision can "wobble" from 37 to 40 bits.* When adding floating point numbers, the precision jumps up or down 3 bits if the mantissa overflows or under flows. Imagine you were limited to just two decimal digits and an exponent: You can add decimals 9.9e1+ 1e0 = 1.0e2 but you can't represent 1.0e2 + 1e0 = 1.01e2 It just rounds down. There is a discontinuity where: over the domain 0 to 9.9e1 the smallest delta is 1e0 But in the neighboring domain of 1.0e2 to 9.9e2 the smallest delta is 1e1. In fixed point, you can do + or - 1 on numbers from -99 to +99. But on 100 to 990 you can only add or subtract 10s. 97 + 10 - 10 is 100. So any accumulation of number operations suffers from "wobble". Now this happens with hexadecimal. When you print the Cortex 40-bit fraction as decimal, sometimes you are precise to 12 decimal digits. Like with 2^40-1. But there is a discontinuity (just add 1) when 40 bits of fraction can't represent the number precisely. It's all rounded to the nearest 16. When you print the decimal result, the 12th digit is garbage. That's why Cortex says it has precision to 11 decimal digits. Precision is lost in addition when you have to line up the smaller number with the bigger number, and the small number falls off. With HFP, there is a jump in imprecision as you cross a threshold of 2^N where N is a multiple of 4. * This problem occurs in any base. It exists in RADIX-100, whenever you cross a power of 100, you lose a "digit" of two decimal places. IEEE-754 minimizes wobble by using base 2. (How does RADIX-100 normalize the number?) Edited August 9 by FarmerPotato ... incorrect math deleted for now ... 1 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted August 8 Author Share Posted August 8 20 hours ago, OLD CS1 said: Shame. I am rather attracted to this dialect of BASIC. It hauls ass and has simple commands for graphics like we saw for other 8-bits of the area (I always despised/envied HPLOT and VPLOT in AppleSoft BASIC.) Could have been a contender. Here is the listing for Cortex BASIC. They mention that it is on a 24K cartridge. Assuming this is (relatively) bug free it should be possible to store it in multiple banks in a cartridge for the TI99 and run it using bank switching. But it wouldn't be trivial. There are some instructions I do not recognize that may be only on the 9995, but I'm sure there would be a workaround. http://www.powertrancortex.com/basicandcdos/Cortex ROM Source.pdf 2 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 9 Share Posted August 9 5 hours ago, FarmerPotato said: (How does RADIX-100 normalize the number?) The absolute value (saving sign) of the result of a radix-100 calculation is normalized by checking the mantissa for leading zero bytes (radix-100 digits) and shifting left, one byte at a time, until the lead byte is nonzero. The exponent is adjusted to make that lead byte the sole, non-fractional, radix-100 digit. If all mantissa bytes are zeros, the first word (sign/exponent byte and the first mantissa byte) is zeroed. Nonzero results are rounded, if necessary. If the result is negative (indicated by saved sign) the first word is negated. ...lee 1 Quote Link to comment Share on other sites More sharing options...
+OLD CS1 Posted August 9 Share Posted August 9 6 hours ago, senior_falcon said: Here is the listing for Cortex BASIC. Digging around that site is fascinating. Certainly for another thread, the most fascinating article was that of the TMS-9909 disk controller. 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 9 Share Posted August 9 10 hours ago, Lee Stewart said: The absolute value (saving sign) of the result of a radix-100 calculation is normalized by checking the mantissa for leading zero bytes (radix-100 digits) and shifting left, one byte at a time, until the lead byte is nonzero. The exponent is adjusted to make that lead byte the sole, non-fractional, radix-100 digit. If all mantissa bytes are zeros, the first word (sign/exponent byte and the first mantissa byte) is zeroed. Nonzero results are rounded, if necessary. If the result is negative (indicated by saved sign) the first word is negated. ...lee 16 hours ago, FarmerPotato said: I recognize this format from the TMS99000's floating point. It is an IBM/360 compatible, single-precision 32 bits. Cortex extends it to 48 bits. See Wikipedia, IBM Hexadecimal Floating Point. It has a shortcoming called "wobbling precision." The first digit, from 0001 to 1111, can have 3 leading zeroes. Even though Cortex' mantissa is 40 bits, its effective precision can "wobble" from 37 to 40 bits.* The smallest normalized mantissa 00012 has 37 bits of precision. It can represent decimal 2^36 or 137,438,953,472. So you can't always represent a number with 12 digits. The 12-digit decimal numbers greater than that can't be represented exactly. Precision is lost in addition when you have to shift a number either way. If you have all 1s, some of them fall off. If you start with 2^40-1 exactly, the mantissa is all 1s. But any number from 1-15 is too small to add to it! When shifting them to align, those small bits fall off. All the numbers between 2^36 and 2^40-1 have that size imprecision. (Mantissa starts with 0001 to 1111) But between 2^40 and 2^44-1 the same situation occurs, however it's worth between 16 and 255. So there is a jump in imprecision as you cross a threshold of 2^N where N is a multiple of 4. * This problem occurs in any base. It exists in RADIX-100. IEEE-754 minimizes it by using base 2. (How does RADIX-100 normalize the number?) The level of computer knowledge in this forum is awe inspiring. 2 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted August 9 Share Posted August 9 16 hours ago, senior_falcon said: There are some instructions I do not recognize that may be only on the 9995, but I'm sure there would be a workaround. The TMS 9995 has four instructions that aren't available in the TMS 9900. MPYS Multiply signed DIVS Divide signed LST Load status register LWP Load workspace pointer The correcsponding TMS 9900 instructions is only unsigned divide and multiply, and only loading of immediate values to the status and workspace pointer registers. The old instructions are available too in the TMS 9995. On the other hand, they seem to make frequent use of macros, and the ability of the TMS 9995 to detect and execute illegal opcodes as macros. An efficient way to call subroutines, so to speak. 1 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 9 Share Posted August 9 52 minutes ago, apersson850 said: The TMS 9995 has four instructions that aren't available in the TMS 9900. MPYS Multiply signed DIVS Divide signed LST Load status register LWP Load workspace pointer The correcsponding TMS 9900 instructions is only unsigned divide and multiply, and only loading of immediate values to the status and workspace pointer registers. The old instructions are available too in the TMS 9995. On the other hand, they seem to make frequent use of macros, and the ability of the TMS 9995 to detect and execute illegal opcodes as macros. An efficient way to call subroutines, so to speak. I remember searching the instruction set for way to do that LWP instruction for round-robin multi-tasking. Eventually I figured out that I could do it "back-handed" by pre-loading R13,14,15 and executing RTWP. Weird, but it worked. 1 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted August 9 Author Share Posted August 9 2 hours ago, apersson850 said: The TMS 9995 has four instructions that aren't available in the TMS 9900. MPYS Multiply signed DIVS Divide signed LST Load status register LWP Load workspace pointer The correcsponding TMS 9900 instructions is only unsigned divide and multiply, and only loading of immediate values to the status and workspace pointer registers. The old instructions are available too in the TMS 9995. On the other hand, they seem to make frequent use of macros, and the ability of the TMS 9995 to detect and execute illegal opcodes as macros. An efficient way to call subroutines, so to speak. These must be macros then. STORE @DS1 FDIV @DS1 FMUL @DS NORMALIZE 0 FADD @TEMP and so on... 1 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted August 9 Share Posted August 9 (edited) 5 hours ago, senior_falcon said: These must be macros then. STORE @DS1 FDIV @DS1 FMUL @DS NORMALIZE 0 FADD @TEMP and so on... The Cortex BASIC printout says it is for the 990's Macro assembler SDSMAC. Could be macros. Then, FADD is a familiar TI "macro instruction", which assembled to an "illegal" opcode. That causes a MID interrupt (shared with level 2) to be handled by software. (On a 99110 the MID interrupt executes a program in internal ROM. If it's not there, then the vector for INT2.) I forgot that the 9995 had MID too. A 9995 couldn't run the same floating point code copied out of the 99110 internal ROM... because 99110 features. But you *could* adapt it, put it in the MID handler, and keep using the same FADD opcode on 9995. This was TI's design for compatibility among all its 9900 family products. Emulation if the feature isn't there in hardware. The 990/10 and 990/12 take this to the extreme--the /12 has gobs of new instructions--but you could still imagine implementing all of those instructions in the MID interrupt, and unmodified code could run on a 9995. * The TMS9900 ignores and skips "illegal" opcodes. (Havoc!) * the 99000 floating point code uses the EVAD instruction. EVAD decodes the operand effective address. You'd have to write that part. Also, Macrostore has some unique "addressing modes". --- Which Marin machine had 9995, and which had 99110? Edited August 9 by FarmerPotato Rewrote the unclear parts 1 Quote Link to comment Share on other sites More sharing options...
Stuart Posted August 9 Share Posted August 9 1 hour ago, senior_falcon said: These must be macros then. STORE @DS1 FDIV @DS1 FMUL @DS NORMALIZE 0 FADD @TEMP and so on... Those (the floating point operations) are defined as XOPs, with the vectors low in memory (see page 20 of the ROM listing) pointing to the code starting on page 490 of the listing. I converted these to BLWPs for the 9900 version. Cortex BASIC also uses illegal opcodes for some functions, which causes a MID interrupt (as Farmer Potato said above), with a MID handler starting on page 31 of the listing to determine the cause of the interrupt (it could be an arithmetic overflow). There's a table of the functions called through the MID mechanism on page 36. I also changed all these illegal opcodes to BLWPs for the 9900 version. 2 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted August 9 Share Posted August 9 4 hours ago, TheBF said: I remember searching the instruction set for way to do that LWP instruction for round-robin multi-tasking. Eventually I figured out that I could do it "back-handed" by pre-loading R13,14,15 and executing RTWP. Weird, but it worked. Another way that TI did that is: LI R8,NEWWP LI R9,NEWPC BLWP R8 3 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 9 Share Posted August 9 14 minutes ago, FarmerPotato said: Another way that TI did that is: LI R8,NEWWP LI R9,NEWPC BLWP R8 Ah. Clever. Thanks For context switching a Forth system once all the workspaces are setup, RTWP is just too temping to avoid. The entire context switch plus test for awake/sleeping is 4 instructions. It would be smaller if I used a register for the status flag instead of a workspace relative variable. 2 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted August 9 Author Share Posted August 9 2 hours ago, Stuart said: Those (the floating point operations) are defined as XOPs, with the vectors low in memory (see page 20 of the ROM listing) pointing to the code starting on page 490 of the listing. I converted these to BLWPs for the 9900 version. Cortex BASIC also uses illegal opcodes for some functions, which causes a MID interrupt (as Farmer Potato said above), with a MID handler starting on page 31 of the listing to determine the cause of the interrupt (it could be an arithmetic overflow). There's a table of the functions called through the MID mechanism on page 36. I also changed all these illegal opcodes to BLWPs for the 9900 version. That is a heck of a lot of work! It is far beyond my level of comprehension. This is a good test for Chat GPT or similar. Here's the source code for Powertran Cortex BASIC. Here are the specs for the TI99. Please convert this so it runs properly on the TI99/4a. I bet it can't, but wouldn't it be cool if it could! 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted August 10 Share Posted August 10 11 hours ago, TheBF said: For context switching a Forth system once all the workspaces are setup, RTWP is just too temping to avoid. I've done the same. Since my console has 64 Kbytes internal RAM, with an ability to overlay everything else that's there from the beginning, I can copy the monitor ROM (0000-1FFF) into RAM, then modify the interrupt vectors and enable RAM over ROM. That way I can decide what the interrupts should do, if I want to. So I used the programmable timer in the TMS 9901 to generate the task switch interrupt. The scheduler had a ReadyQ with the tasks waiting to run. In the interrupt service, I took the next set of R13-R15 form the ready-to-run queue, plugged into R13-R15 and RTWP back to the process that should run this time. calling the first procedure the very first time, to launch the whole thing, requires faked values to be injected into R13-R15, then "return" to a process you never came from. 4 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 10 Share Posted August 10 5 hours ago, apersson850 said: I've done the same. Since my console has 64 Kbytes internal RAM, with an ability to overlay everything else that's there from the beginning, I can copy the monitor ROM (0000-1FFF) into RAM, then modify the interrupt vectors and enable RAM over ROM. That way I can decide what the interrupts should do, if I want to. So I used the programmable timer in the TMS 9901 to generate the task switch interrupt. The scheduler had a ReadyQ with the tasks waiting to run. In the interrupt service, I took the next set of R13-R15 form the ready-to-run queue, plugged into R13-R15 and RTWP back to the process that should run this time. calling the first procedure the very first time, to launch the whole thing, requires faked values to be injected into R13-R15, then "return" to a process you never came from. If TI had understood where the future of desktop machines was going your architecture with a 99000 processor could have challenged the IBM PC. (Assuming a nice O/S, good developer support and a very large marketing budget) But it does sound like the kind of thing we were all waiting for. The "TI-99/10". 1 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted August 10 Share Posted August 10 On 8/8/2023 at 10:28 PM, Lee Stewart said: The absolute value (saving sign) of the result of a radix-100 calculation is normalized by checking the mantissa for leading zero bytes (radix-100 digits) and shifting left, one byte at a time, until the lead byte is nonzero. The exponent is adjusted to make that lead byte the sole, non-fractional, radix-100 digit. If all mantissa bytes are zeros, the first word (sign/exponent byte and the first mantissa byte) is zeroed. Nonzero results are rounded, if necessary. If the result is negative (indicated by saved sign) the first word is negated. ...lee Thanks, I was wondering if it made the first digit non zero or 1-99, or sometimes multiplied or divided by 10 to make the first digit from 1-9. Would be a waste of cpu time probably. Quote Link to comment Share on other sites More sharing options...
+RXB Posted August 10 Share Posted August 10 On 8/8/2023 at 2:36 PM, senior_falcon said: Here is the listing for Cortex BASIC. They mention that it is on a 24K cartridge. Assuming this is (relatively) bug free it should be possible to store it in multiple banks in a cartridge for the TI99 and run it using bank switching. But it wouldn't be trivial. There are some instructions I do not recognize that may be only on the 9995, but I'm sure there would be a workaround. http://www.powertrancortex.com/basicandcdos/Cortex ROM Source.pdf When I assembled original XB 110 ROMs and GPL source code was using a few macro routines that did not exist for any 9900 Assembler or GPL Assembler. It was written for the 990 computer to assemble for use in making the GPL and Assembly for the 9900. So DO WHILE and ENDIF routines I had to figure out how to make them work in the Ryte Data GPL assembler and TI Editor Assembler. The source code for XB 110 that I released had the conversions without the Macros. Looking at your source code post of Cortex Basic most of it can be used in a 9900, but some of it does present a problem. 1 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted August 10 Share Posted August 10 21 hours ago, FarmerPotato said: Another way that TI did that is: LI R8,NEWWP LI R9,NEWPC BLWP R8 I didn't even know that BLWP R8 was a valid instruction. Quote Link to comment Share on other sites More sharing options...
apersson850 Posted August 10 Share Posted August 10 That's the beauty of general addressing modes. B R8 is a valid instruction. You just have to make sure that there's a meaningful opcode in R8, and the following registers you need. If you don't JMP somewhere, it will run through R8-R15 and then continue in memory past your workspace. I noticed in the Cortex BASIC listing that they use the trick of calculating a proper STCR or LDCR instruction, since they need a variable number of bits, in R8 and then they do X R8 to run it. In that case execution will only be of the instruction in R8, then continue after the X instruction. 1 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.