Jump to content
IGNORED

How to ID a 9995, or which CPU?


Recommended Posts

https://cdn.preterhuman.net/texts/computing/msx/ti hardware compendium.txt

 

*
*
*
*  CPU identification routine by Jeffrey H. White
*  (c) Copyright 1991
*
*  Usage:  BLWP @CPUID
*
*  Returned values in R1:  if 9900,  = 1
*                          if 9995,  = 2
*                          if 99000, = 3 (Privileged Mode)
*                                    = 4 (User Mode)
*
CPUID  DATA $-16            R8 location
       DATA CPUPC           R9 location
CPUPC  BES  12              skip over R10-R15
       LIMI 0               try to turn off interrupts
       LWPI CPUID-16-6      to preserve R13-R15, new Rx = old R(x-3)
       STST R15             store status
       SLA  R15,12          are interrupts off
       JNE  C99000          no, then definitely in 99000 User Mode
       STWP R13             store current WP
       LI   R14,CONTIN      trick with PC required by LST-less 9900
       LI   R15,>0020       after RTWP, ST10 will be 1 only on 9995/99000
       RTWP                 load ST, keep current WP, and execute next
CONTIN LI   R14,>0001       load value to return if 9900
       STST R15             ST10 was not affected by previous instruction
       SLA  R15,7           check ST7 for Privileged (Supervisor) Mode
       JLT  C99000          ST7=1 always on 99000 in User Mode
       JEQ  C9900           ST10=0 always on 9900
       MOV  @>FFFA,R15      9995 on-chip decrementer location
       AI   R15,>8000       most distant value from decrementer
       MOVB R15,@>FFFB      byte writes to 9995 decrementer mess up both
       AI   R15,>8000       restore register to previous decrementer value
       CB   R15,@>FFFA      decrementing is not fast enough for bytes to equal
       JNE  C9995           on 99000, memory or not, >FFFA will not change
       INC  R14             only executes if 99000 is found
C9995  INC  R14             only incremented once if 9995
       MOV  R15,@>FFFA      restore the value
C9900  LWPI CPUID-16        restore entry WP
       MOV  R11,@>0002(R13) put at caller R1
       RTWP                 finished
C99000 LI   R14,>0004       value returned if 99000 User Mode
       JMP  C9900           go exit

------------------------------------------------------------------------------

*
*  VDP identification routine by Jeffrey H. White
*  (c) Copyright 1991
*
*  Usage:  BLWP @VDPID
*
*  Returned values in R1:  if 9918A, = 1
*                          if V9938, = 2
*                          if V9958, = 3
*
VDPWS  BSS  32
VDPID  DATA VDPWS
       DATA VDPPC
VDPPC  LI   R10,1
       LI   R0,>0F04
       BLWP @VWTR
VDPST  MOVB @VDPSTA,R12
       JGT  VDPST
       JEQ  V9918A
       MOVB @VDPSTA,R12
       JLT  V99X8
       JMP  V9918A
V99X8  LI   R0,>0F01
       BLWP @VWTR
       MOVB @VDPSTA,R12
       SLA  R12,5
       JLT  V9958
       JMP  V9938
V9958  INC  R10
V9938  INC  R10
V9918A LI   R0,>0F00
       BLWP @VWTR
       LI   R0,>07F4
       BLWP @VWTR
       MOV  R10,@>0002(R13)
       RTWP
*
  • Like 5
Link to comment
Share on other sites

To my knowledge, the 9995-MP9537 (used in the 99/8) neither offers on-chip RAM nor a decrementer. This is the way I implemented it in MAME as well.

 

My suggestion would be to use one of the 9995 commands like LWP or LST. You do a LST, then a STST and compare. You should make sure that some bit like the EQ bit is set before.

Link to comment
Share on other sites

@mizapf, not sure how using LWP or LST would be useful in determining 9995-MP9537 or true 9995.  My code already does play with ST bits to determine CPU type/mode.

 

The 9900 does not implement all ST bits, while the 9995 and 99000-series do — though the 9995 does not define them all.  I.e., the non-implemented ST bits on the 9900 will always return 0.  The undefined 9995 ST bits can be set with LST or RTWP — code can define what they mean.  The 99000 ST bits are all defined, and in user mode they cannot all be affected by code.

 

I wonder if the 9995-MP9537 implements the on-chip CRU bits.

 

There is also the 69689:  https://cdn.preterhuman.net/texts/computing/msx/SMJ68689 Data Sheet.pdf

Edited by Jeff White
Link to comment
Share on other sites

@mizapf, I think the decrementer is a safe way, whether it is running or not.

 

The 9995 decrementer is located at FFFA.  For simplicity, assume the value is 0000.  The code does the following:

 

(1) Moves at FFFA into R15.  R15 contains 0000.

(2) 8000 is added to R15.  R15 contains 8000.

(3) R15 even byte is written to FFFB.  On 9995, FFFA contains 8080 because byte written changes both bytes.  On 99000, FFFA contains 0080 — same as 9900 (which has already been excluded to get to this code).

(4) 8000 is added to R15. R15 contains 0000 (original value).

(5) R15 even byte value 00 is compared to FFFA even value — 00 on 99000, non-zero and likely 80 on 9995.  Equal means 99000, non-equal means 9995.

  • Like 1
Link to comment
Share on other sites

The 99/8 uses the variant 9995-mp9537 which has no decrementer; FFFA/FFFB behaves like a normal RAM location. If you exclude the 9900 at that point already, you're safe.

 

But I'm quite sure that the decrementer test would falsely identify the CPU in the TI-99/8 as a 9900.

 

Another way could be the MID interrupt.

  • Like 1
Link to comment
Share on other sites

On 2/24/2022 at 4:50 AM, Jeff White said:

Is anyone concerned about programs running on the 99/8?  What would break if a REAL 9995 was installed on a 99/8 that is not already broken?

 

Maybe @speccery can check the code with 99105.

I'll test it on my 99105. I spent yesterday and today a couple hours in getting my FPGA + 99105 system up and running again. This was puzzling, since I tried it not too long ago and my boards were working fine. Nothing I did made things stable. Until I realized the culprit was a bad USB cable! What a time waster! And hard to find, as I was able to initialise the boards but I did not get correct video out. When I switched to another cable things immediately worked. I suppose the +5V power delivery in the bad cable was somehow intermittent.

Link to comment
Share on other sites

I get 3 with the TMS99105, which is what this should be: 99000 in privileged mode.

 

I had to change the code somewhat, since it assumes to be running in RAM, i.e. the workspace used by the code is located just before the code in address space. This is not good for me, since I run this code from my test boot "ROM" (write protected RAM) in the first 8K of the address space. My test code replaces the normal TI-99/4A ROM with all kinds of test code, including this one.

 

But with my test program something funny happens when calling CPUID, after calling it and displaying the result on the screen, the next thing my test code does is that it enables interrupts. I checked that after BLWP @CPUID the workspace is restored properly even after my changes to the code. But the execution stops after LIMI 2, I assume this happens since the interrupt routine somehow gets stuck. Would not be surprise, I have a simple interrupt routine which has been working so far but apparently no longer... I also checked the contents of ST before and after CPUID and it does not appear to anything funny there.

 

EDIT: I modified my interrupt routine to change screen border color on every interrupt. It results in an animated border with lines, meaning that the the interrupt request is not cleared for some reason after the interrupt, so the interrupt is triggered immediately again. Could be a bug in my FPGA design.

Edited by speccery
  • Like 3
Link to comment
Share on other sites

I asked what the 9900 does on undefined opcodes, and got the answer that it just skips them.

 

So I thought of a couple more characteristics for  CPUID to use:

 

1. Do a MPYS instruction. If nothing happens, it's older than 9995.

2. For 9981 or 9940, probably could test the address space; they only have 16K. Not too useful. 

3. Test for working CRU flag 1EEA. A 9995 used defined internal flag only on 9995. Harmless on Geneve. 99/8? dunno. Actually a PRIVOP on 99000, which could be a problem.

 

One problem with CPUID: LIMI 0 is a privileged instruction, so it causes a Level 2 PRIVOP interrupt for 99000 in user mode. 

 

Still, on the 99000, its Level 2 PRIVOP can be masked, in which case the interrupt doesn't fire off right away.  I wish this wasn't the case. Wonder what the idea was there. MID is level 2 but can't be masked.

 

Great discussion, y'all.

Link to comment
Share on other sites

On 2/25/2022 at 1:31 PM, speccery said:

But the execution stops after LIMI 2, I assume this happens since the interrupt routine somehow gets stuck. Would not be surprise, I have a simple interrupt routine which has been working so far but apparently no longer... I also checked the contents of ST before and after CPUID and it does not appear to anything funny there.

 

EDIT: I modified my interrupt routine to change screen border color on every interrupt. It results in an animated border with lines, meaning that the the interrupt request is not cleared for some reason after the interrupt, so the interrupt is triggered immediately again. Could be a bug in my FPGA design.

If you are in a PRIVOP level 2 interrupt, you must clear cru 1FDC, PRIVOP. Similarly 1FC8, Arithmetic Fault (if enabled). See page 28 of the 99000 data manual. If they are raised, the level 2 routine must clear them, or be re-triggered.

 

In CPUID, I see a LIMI 0, which would raise PRIVOP in 99000 user mode. (User can't disable interrupts!)

 

Edited by FarmerPotato
  • Like 1
Link to comment
Share on other sites

7 hours ago, FarmerPotato said:

If you are in a PRIVOP level 2 interrupt, you must clear cru 1FDC, PRIVOP. Similarly 1FC8, Arithmetic Fault (if enabled). See page 28 of the 99000 data manual. If they are raised, the level 2 routine must clear them, or be re-triggered.

 

In CPUID, I see a LIMI 0, which would raise PRIVOP in 99000 user mode. (User can't disable interrupts!)

Thanks for the tips! Need to try those out. Like I wrote, if I run the same code but without calling CPUID everything works. The same code with CPUID call in place gets stuck, so perhaps indeed one of those flags you mention is at play.  The processor should be in privileged mode, at least I am not on purpose changing it to user mode. Indeed the CPUID return value 3 suggests that this is the case.

  • Like 1
Link to comment
Share on other sites

  • 1 month later...
  • 1 month later...
On 2/15/2022 at 8:30 PM, Jeff White said:

I do not know that the CPUID routine was ever tested with a 99000-series CPU.  The code was tested on 99/4A and Geneve, which do produce the correct results.  Not sure what a 99/8 would do.

 

I believe that a bug in the 99000 detect is when

 

AI R15,>8000

 

causes ST4=1 (Arithmetic Fault.) 

 

If ST10 is also set, (which it is!) the 99000 sets the Arithmetic Fault error cru bit in >1FCA.
 

ST10 is AFIE in the 99000.


 

If any of the 3 cpu error bits is set when interrupts are enabled (LIMI 2) the 99000 traps to INT2. It repeats each time interrupts are enabled. This could explain  @speccery’s lockup. 

Long explanation:

 

I was writing  the INT2 handler which needs to handle all the CPU error types. 

CPUID does:

 

1. Try to set LIMI to 0. If this fails we must be in 99000 user mode.  First bug: this assumes prior interrupt mask state not 0. Reasonable assumption? Perhaps. 

 

On the other hand, if interrupt mask is >1, then the LIMI causes PRIVOP error and the CPU will vector to INT2.  INT2 may or may not be coded to return! So this may go off the rails in 99000 user mode. 


(I see I already said this in an earlier post!)

 

2. To rule out 9900, it tries to  set a status bit, ST10.  Always zero on 9900. Unused, but settable on the 9995. The problem is that this is AFIE on the 99000. It enables Arithmetic Fault interrupt.  It gets set to 1 if in 99000 supervisor mode. 
 

The later instruction AI R15,>8000 causes an arithmetic fault. It’s a signed arithmetic overflow. (So don’t leave AFIE on!)

The AF interrupt will take place as soon as LIMI 2.  Not in the CPUID routine, but somewhere later.


I bet that is why @speccery’s CPU locks up. 


Behavior of ST ERR

 

P. 28 of the 99000 data book describes the “error status register”. (I’m calling this ERR ST.) 

I verified the table on page 28. 

PRIVOP >4000

ILLOP >2000

AF >0010           coincidentally, the same bit used in the ST register.

 

SBZ worked to reset bits, using the addresses in the table.   But the text below it is full of address typos.

I also tried the RSET instruction and it definitely clears ST ERR. (Also RSET requires supervisor mode.) 

 

The bit values I observe in ERR ST:
An INT2 handler must clear the AF condition in ST ERR bit and also ST4 (AF occurred) —else the interrupt will repeat after RTWP (or any LIMI 2). Or you can disable AFIE.
 

Macrostore Surprise

 

my ILLOP test was to execute:

 

DATA >0C0C    undefined, MID

 

Which jumps to Macrostore!  It is the Macrostore program that gets a crack at the opcode.


Without valid Macrostore ROM, I see bad stuff happen (random, but usually infinite loop.)

 

 if the Macrostore program (of the 99110) doesn’t want the opcode, (ie it’s not floating point or some other extension) THEN the program sets ILLOP and returns. Then INT2 occurs. 

Without Macrostore, there’s no ILLOP interrupt!

 

So.. I have my CPU set to External Macrostore (conveniently mapped to my ROM, not a separate address space.)  It was full of garbage test patterns — so lockup. 
 

Cured: I loaded @pnr’s excellent dump of the 99110 ROM. On the first try, ILLOP worked perfectly. (and now I can try all the 99110 instructions!)

 

At last, I’ve got INT2 printing messages for all the cases, and clearing them. 

 

 

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