Jump to content
IGNORED

CORTEX BASIC


senior_falcon

Recommended Posts

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 by senior_falcon
  • Like 2
Link to comment
Share on other sites

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.

 

  • Like 3
Link to comment
Share on other sites

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.

  • Like 4
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.  ;) 

 

Link to comment
Share on other sites

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 by FarmerPotato
... incorrect math deleted for now ... 
  • Like 1
Link to comment
Share on other sites

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

  • Like 2
Link to comment
Share on other sites

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

  • Like 1
Link to comment
Share on other sites

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. 

  • Like 2
Link to comment
Share on other sites

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.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

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.

 

  • Like 1
Link to comment
Share on other sites

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...

 

  • Like 1
Link to comment
Share on other sites

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 by FarmerPotato
Rewrote the unclear parts
  • Like 1
Link to comment
Share on other sites

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.

 

  • Like 2
Link to comment
Share on other sites

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

 

  • Like 3
  • Thanks 1
Link to comment
Share on other sites

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. 

 

 

 

  • Like 2
Link to comment
Share on other sites

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!

  • Like 1
Link to comment
Share on other sites

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.

  • Like 4
Link to comment
Share on other sites

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".

  • Like 1
Link to comment
Share on other sites

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. 

 

 

 

 

Link to comment
Share on other sites

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.

 

  • Like 1
Link to comment
Share on other sites

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.

  • Like 1
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...