+FarmerPotato Posted February 11, 2022 Share Posted February 11, 2022 Does anyone have ideas on how code might tell if it is running on a 9900 or 9995? How about 99105? I don’t have an immediate application for this, just some ideas. Quote Link to comment Share on other sites More sharing options...
+dhe Posted February 11, 2022 Share Posted February 11, 2022 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 * 5 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted February 12, 2022 Author Share Posted February 12, 2022 @dhewow, that is some code. Quote Link to comment Share on other sites More sharing options...
Jeff White Posted February 16, 2022 Share Posted February 16, 2022 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. Quote Link to comment Share on other sites More sharing options...
+mizapf Posted February 16, 2022 Share Posted February 16, 2022 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. Quote Link to comment Share on other sites More sharing options...
Jeff White Posted February 16, 2022 Share Posted February 16, 2022 (edited) @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 February 16, 2022 by Jeff White Quote Link to comment Share on other sites More sharing options...
+mizapf Posted February 16, 2022 Share Posted February 16, 2022 No, it would be useful to tell apart the 9900 from the 9995, since the decrementer is not a safe way. Quote Link to comment Share on other sites More sharing options...
Jeff White Posted February 17, 2022 Share Posted February 17, 2022 @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. 1 Quote Link to comment Share on other sites More sharing options...
+mizapf Posted February 17, 2022 Share Posted February 17, 2022 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. 1 Quote Link to comment Share on other sites More sharing options...
Jeff White Posted February 24, 2022 Share Posted February 24, 2022 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. 2 Quote Link to comment Share on other sites More sharing options...
Stuart Posted February 24, 2022 Share Posted February 24, 2022 Just tried it on my boards and all four combinations are reported correctly (using a 9995 with a decrementer). 2 Quote Link to comment Share on other sites More sharing options...
speccery Posted February 25, 2022 Share Posted February 25, 2022 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. Quote Link to comment Share on other sites More sharing options...
speccery Posted February 25, 2022 Share Posted February 25, 2022 (edited) 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 February 25, 2022 by speccery 3 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted February 27, 2022 Author Share Posted February 27, 2022 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. Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted February 27, 2022 Author Share Posted February 27, 2022 (edited) 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 February 27, 2022 by FarmerPotato 1 Quote Link to comment Share on other sites More sharing options...
speccery Posted February 28, 2022 Share Posted February 28, 2022 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. 1 Quote Link to comment Share on other sites More sharing options...
Jeff White Posted February 28, 2022 Share Posted February 28, 2022 @FarmerPotato, @speccery, note that CPUID has 2 checks for 99000 user mode. Why did I write it that way? Quote Link to comment Share on other sites More sharing options...
+dhe Posted April 27, 2022 Share Posted April 27, 2022 Is the CPUID Code as good as it gets, or is there better code? Is there a way to check for the F18A VDP? Quote Link to comment Share on other sites More sharing options...
Stuart Posted April 27, 2022 Share Posted April 27, 2022 3 hours ago, dhe said: Is the CPUID Code as good as it gets, or is there better code? Is there a way to check for the F18A VDP? 10 INPUT "ARE YOU USING AN F18A",A$ ? ISTR there is a way. Checked the F18A thread? Quote Link to comment Share on other sites More sharing options...
+dhe Posted April 27, 2022 Share Posted April 27, 2022 1 hour ago, Stuart said: 10 INPUT "ARE YOU USING AN F18A",A$ ? ISTR there is a way. Checked the F18A thread? You mean the one with 100's of posts? ? Quote Link to comment Share on other sites More sharing options...
Stuart Posted April 27, 2022 Share Posted April 27, 2022 (edited) 2 hours ago, dhe said: You mean the one with 100's of posts? ? Yep, that's the one. See pages 2 and 5 of https://atariage.com/forums/applications/core/interface/file/attachment.php?id=318329. Edited April 27, 2022 by Stuart 1 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted June 23, 2022 Author Share Posted June 23, 2022 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. 3 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.