Jump to content
kl99

Tms9900 Disassembling Rules and Opcode Table

Recommended Posts

Hi Guys!
I am still on trying to reconstruct the system source code for the Tomy Tutor and would need some help.

 

It is a bit complicated since that 32KByte ROM chip is containing all: Tms9900 assembler instructions, Tms9900 assembler data, GPL instructions, GPL data.

So to better get a grip of what is what I would like to flag certain memory locations being machine code, and therefore not GPL code.

The 2nd ROM chip is almost completed (only beginning and end are unclear) and it revealed that it contains the ROM code for TI Extended Basic, stripped by some features, assembled to run at different CPU addresses.

So we can now actually assemble that binary of the 2nd ROM chip by assembling the modified TI Extended Basic assembly source code files.

 

 

For this topic I would like to ask, if I assume these things correctly?

 

1. If you start a computer system and the Tms9995 PC (Program Counter) get values of certain addresses, it is 100% that all these addresses are the start address of one machine instruction. So I can use the trace output of some emulation or debugger to get a list of start addresses of actual machine instructions.

2. From looking at the three bytes at each of these addresses in point 1 there is only one matching machine instruction that can be disassembled to its assembly instruction. So there is no need to assume and guess here.

3. From only analyzing each of this confirmed instructions I can look at the confirmed Jump Instructions, precisely at their target address. Those target addresses will always be the start address of one assembly instructions. The same is true for Branch Instructions and their target address. So by doing this I can extend my list of confirmed start addresses for assembly instructions.

4. Points 1 to 3 can be ruled out to be DATA, BYTE or TEXt statements, unless there was some weird double usage of assembled byte or word values as constants to win single bytes.

5. Machine instructions are executed in sequence, one after another. So from a confirmed start address of one machine instruction I can identify that assembly instructions and there is no guessing how long that instruction is and that reveals the next start address of an assembly instruction and so on. That execution sequence is broken by which opcodes? I assume Jump and Branch Instructions, RT. Maybe X, XOP? Can CRU instructions or LIMI change the program flow? Is it allowed to have DATA within your program flow? Wouldn't that potentially break the opcode parser?

 

Is there a Tms9900 opcode table? Not a list of opcodes but a full mapping of a complete instruction line towards its hex code value. So it would have a line for each potential version of a certain opcode, dependent on which register is used and so on.

  • Like 2

Share this post


Link to post
Share on other sites
  1. Where the CPU tries to execute code, there should be assembly code. Otherwise there is a bug, which causes it to try to execute data. Which it will do, but it rarely makes sense.
  2. An instruction is two bytes, not three. But they are variable length, so an instruction could be followed by one or two addresses, or an immediate value.
  3. Yes, a JMP (or conditional jump), Branch and Branch and Link should point to valid addresses. But DATA words can, by chance, have the same value as the opcode of a branch instruction.
  4. You're right in that occasionally, programmers do find a byte with a value they need somewhere in the code, and use that, to save defining a constant. It's a bad practice, but it happens. At least back in the days when memory were small.
  5. Yes, instructions are executed in sequence. The length of the instructions is variable. One, two or three words long is what the TMS 9900 and TMS 9995 support.
    Jumps (conditional sometimes, unconditional always) break the flow. So does B, BL, BLWP and RTWP. There is no RT instruction. It's really a B *R11.
    X will execute the instruction at the address pointed to. If that instruction is some kind of branch, then it will break the flow. If it's a JUMP, the jump will be done relative to the X instruction, not relative to the instruction actually executed.
    XOP behaves like BLWP. It's a vectored branch with a new workspace and address. The difference compared to BLWP is that the vectors are at predefined addresses, that you can select one out of 16 of them and that you can specify a general address as an operand. That address will be in R11 when the implied BLWP has been executed. XOP is intended to add up to 16 new instructions to the CPU, instructions which are implemented as software routines, but otherwise behave as single general address instructions (like INC or B).
    LIMI by itself doesn't alter the program flow. But if you use LIMI so that you enable interrupt, and an interrupt is pending, then it will immediately alter the flow. Or an interrupt could occur later, while the mask still allows it, which means that an interrupt could occur at any place. But the whole idea with interrupts is that eventually, they return to the same place again, so you don't need to worry about them.

I've never seen an opcode table with 65536 entries. They tend to contain the main instruction opcode and specify which additional fields will contain the six bits of a general address description, the jump offset or whatever else is in the instruction.

 

  • Like 1

Share this post


Link to post
Share on other sites

@kl99Klaus, for your investigations, you should probably consider building MAME with certain debug flags so that you can get an output of addresses directly from the emulator. I can give you instructions how to do that.

Share this post


Link to post
Share on other sites

If you have the full 32K rom dumped, you might want to consider disassembling with Tom Freeman's DiskAssembler (DKA) under MDOS mode on the Geneve.  You can define blocks that are then produce assembly code with DATA statements, etc.  DKA under MDOS mode, you could easily handle the full 32K block file as a single program image file instead of dealing with a fractured file.

 

Beery

 

  • Like 3

Share this post


Link to post
Share on other sites

I'll throw in my 5 cents:

- I recently wrote a TMS9900 disassembler in C (I used it when running simulator of my Verilog TMS9900 - GTKWave which I use for simulation result display can interface with an external program for decoding various things). If you want to use it just let me know. It's a simple stateless disassembler. It currently supports only TMS9900 instruction set, not TMS9995, but adding those instructions would be trivial.

- If you want I can create for you a table of all 64K opcodes with the aforementioned disassembler.

- I would also try out xda99 (written in Python by Ralph Benzinger) for disassembly work. I use his xas99 all the time.

- Forgive me not being familiar with Tomy Tutor, but why would it use GPL? Did they license the Basic from TI? Otherwise I don't understand why they would have used GPL. If I was them I would have done the Basic interpreter etc. in normal TMS9995 assembly code.

- With regards to the comments made above, it's good to note that sometimes programmers embed data words in machine code. For example I have used in some of my assembly programs a simple setup where after a BLWP to a routine there are some data words which are parameters to the routine called with BLWP. The routine being called advances the return address as it uses that data, so it will return not to the address immediately after the BLWP but sometime later. The same thing can happen with BL and XOPs. However, these type of parameters are typically only a few words long and will not throw a disassembler off course too much.

Share this post


Link to post
Share on other sites

And another thing: I would be interested in adding Tommy Tutor support to my icy99 project, as I'd like to have at least a FPGA version of it. My understanding is that the Tomy Tutor is basically TMS9995+TMS9918+some simple discrete logic, so implementing it in FPGA form would be probably simpler than for example TI-99/4A.

  • Like 2

Share this post


Link to post
Share on other sites

This is the sort of thing that any disassembler will have problems with, as alluded to above:

 

06A0         BL @LOADER       Load VDP registers.

2426
0280         BYTE >02,>80+R0  Graphics 2 mode, external video off.
8081         BYTE >80,>80+R1  16K, no display, no interrupt, graphics 2, size & mag=0.
0682         BYTE >06,>80+R2  PNTBA=>1800. Screen image table.
FF83         BYTE >FF,>80+R3  CTBA=>2000. Colour table.
0384         BYTE >03,>80+R4  PGTBA=>0000. Pattern descriptor table.
3685         BYTE >36,>80+R5  SNTBA=>1B00. Sprite name table.
0786         BYTE >07,>80+R6  SPGBA=>3800. Sprite pattern generator (descriptor) table.
0087 BDCOL   BYTE >00,>80+R7  Backdrop=background colour.
0000         DATA 0

04C6         CLR R6           Write nulls to VRAM.
0207         LI R7,VRAMW

 

The LOADER routine advances the BL return address over those bytes of data, but a disassembler won't know that, and will deliciously disassemble the two words after BL @LOADER as CI R0,>8081, then (I think) a BL R2, and so on.

Share this post


Link to post
Share on other sites

You can give my disassembler in TIImageTool hints that a branch to some address has n words of DATA behind.

 

"param(proc, count): BL/BLWP to this location is followed by a fixed number of DATA words"

 

The list must be fixed, of course.

  • Like 1

Share this post


Link to post
Share on other sites

I wrote a disassembler in Pascal once. Since the UCSD p-system runs independent of any program module, that allowed me to disassemble whichever module I wanted. That had ROM, that is.

  • Like 1

Share this post


Link to post
Share on other sites
11 hours ago, speccery said:

- Forgive me not being familiar with Tomy Tutor, but why would it use GPL? Did they license the Basic from TI? Otherwise I don't understand why they would have used GPL. If I was them I would have done the Basic interpreter etc. in normal TMS9995 assembly code.

Tomy BASIC is in fact TI Extended Basic.

TI Extended Basic Source code (thanks to RXB), modified to assemble towards different CPU locations, stripped by some features will assemble into the binary that sits in the ROM2 chip of the Tomy Tutor Computer.

ROM2 chip has 16 K but contains the 12K Rom block of TI XB (2 Banks with 8 KB but they share 4 KB), ending up in >9050 - >B900 of the CPU memory.

This proof was only done last month and we hope to hear whether this copy was licensed or pirated.

 

This is where it starts being interesting. We know TI Extended Basic heavily depends on GPL, actually 24K in Grom banks, and might also use the console GPL code. However the Tomy is not having any Grom chips. The necessary GPL code must sit somewhere in the Tomy ROM1 chip. But the same chip also contains all the assembly code for the console. So that makes disassembly of ROM1 (0000-7FFF) a bit more tricky than usual, as we have not only DATA and Tms9995 assembly instructions, but also Gpl and its DATA statements. So far I only found a few tables in ROM1 that are also in the TI XB Gpl sourcecode. Therefore I would like to identify first memory ranges of proofed TMS assembler code to no longer search in wrong locations for Gpl instructions.

The gain of all this would be not only knowledge on Tomy Tutor and being able to extend its BASIC but actually seeing their solution to run Gpl code from normal CPU memory and we might even see a port of Tomy Basic as cartridge on the 99/4A.


My current assumption is that ROM1+ROM2 contain the TI XB and some modified TI console rom. The disassembly should be of help identifying the origin of its system rom and then take the original source code for that origin (example: 99/4 system rom) and repeat the modifications so it compiles into the ROM binaries of the Tomy Tutor. This approach would provide the full source code with original comments of the TI developers, nice variables and structure towards a unknown system to be able to follow what is going on. This was achieved so far for the Tms99xx Assembly part of Tomy Basic (=Tms99xx Assembly of TI XB) (https://github.com/kl9900/TMS9900Family/tree/master/Consoles/TomyTutor/Rom2)

Mostly only existing code lines had to be commented out from TI XB in order to produce the Tomy Basic ROM.

 

  • Like 2

Share this post


Link to post
Share on other sites
12 hours ago, speccery said:

And another thing: I would be interested in adding Tommy Tutor support to my icy99 project, as I'd like to have at least a FPGA version of it. My understanding is that the Tomy Tutor is basically TMS9995+TMS9918+some simple discrete logic, so implementing it in FPGA form would be probably simpler than for example TI-99/4A.

That computer is such a clone of the 99/4(A). Not just software wise but also hardware wise:

TMS9995 cpu (I assume the system rom is copied from 99/4 like the BASIC and therefore not using any TMS9995 only instructions)

TMS9918 video

TMS9919 sound

256 Bytes CPU RAM only.

16 KBytes VRAM.

  • Like 1

Share this post


Link to post
Share on other sites
12 hours ago, speccery said:

- If you want I can create for you a table of all 64K opcodes with the aforementioned disassembler.

I found an approach to create such a table. Yesterday evening I worked on the approach and created all possible values from 1100 to 3FFF.

Will continue and publish a table on my website ti99.eu

Would ask you guys then to verify that table.

  • Like 1

Share this post


Link to post
Share on other sites
18 hours ago, BeeryMiller said:

If you have the full 32K rom dumped, you might want to consider disassembling with Tom Freeman's DiskAssembler (DKA) under MDOS mode on the Geneve.  You can define blocks that are then produce assembly code with DATA statements, etc.  DKA under MDOS mode, you could easily handle the full 32K block file as a single program image file instead of dealing with a fractured file.

 

Beery

 

Beery the problem is not having 32K of data to analyze but that the file includes both assembly instructions and GPL instructions and that this fact screws up the automatic disassembly tool approach. So that is why I asked how a disassembler internally works and does it assumptions. Knowning those I can repeat what is safe to be used in this case and NOT doing those things that screw up the outcome in this case. This is true for both disassemblers, be it for GPL or Tms99xx assembler.

That is why I asked what facts I can use, like that addresses the PC stored are for sure Tms99xx assembly code lines, and working from the known good disassembled parts towards the unknown.

Share this post


Link to post
Share on other sites

There is no problem running GPL code from normal memory. The TI 99/4A does something similar when you use the p-system. The p-code interpreter can interpret p-codes stored in any kind of memory. It exists in two slightly different versions in the system, due to the fact that if you read p-code from VDP RAM or from GROM, then the address is autoincrementing. But if you read p-code from CPU RAM, you need to autoincrement the address you are reading from (the PME's instruction pointer, implemented as a register in the TMS 9900) yourself.

Share this post


Link to post
Share on other sites
7 hours ago, apersson850 said:

There is no problem running GPL code from normal memory. The TI 99/4A does something similar when you use the p-system. The p-code interpreter can interpret p-codes stored in any kind of memory. It exists in two slightly different versions in the system, due to the fact that if you read p-code from VDP RAM or from GROM, then the address is autoincrementing. But if you read p-code from CPU RAM, you need to autoincrement the address you are reading from (the PME's instruction pointer, implemented as a register in the TMS 9900) yourself.

Very much like XB does exactly that same thing, runs from VDP or RAM depending on 32K exists or not.

Share this post


Link to post
Share on other sites
10 hours ago, kl99 said:

Tomy BASIC is in fact TI Extended Basic.

TI Extended Basic Source code (thanks to RXB), modified to assemble towards different CPU locations, stripped by some features will assemble into the binary that sits in the ROM2 chip of the Tomy Tutor Computer.

ROM2 chip has 16 K but contains the 12K Rom block of TI XB (2 Banks with 8 KB but they share 4 KB), ending up in >9050 - >B900 of the CPU memory.

This proof was only done last month and we hope to hear whether this copy was licensed or pirated.

 

Thanks, interesting! So based on what you wrote in the other message, they only would use the internal RAM of the TMS9995 CPU and VDP memory.

  • Like 1

Share this post


Link to post
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.

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