Introduction
The TLCS-900/H is the 16/32-bit CPU core Toshiba used in its TLCS-900 microcontroller family. The best known chip with it is the TMP95C061, the processor of the SNK Neo Geo Pocket and Pocket Color, which runs it at 6.144 MHz (the figure the RACE emulator’s source uses). The core has 32-bit registers in four banks, a 24-bit address space (16 MiB), is little-endian, and has an instruction set built on a prefix scheme: most instructions are a prefix byte that chooses an operand (a memory address of one of nine kinds, or a register), followed by a second byte that chooses the operation, followed by any immediate data. Instructions are one to seven bytes long.
The explorer’s disassembler is explorer/cpu/tlcs900/ (our own code). It is used by the Neo Geo Pocket ROM viewer
and decodes an instruction at every byte of a region (the length depends on the prefix, the memory operand and the second byte), laying the results in columns the way it does for x86 and Z80.
Options: number syntax ($1F or Toshiba’s 1FH) and how a register of an absolute bank is written.
The pages
- Registers and banks: XWA XBC XDE XHL (four banks), XIX XIY XIZ XSP, the status register SR with its flags, the register code table and the control registers.
- Addressing modes: the prefix bytes
$80to$F7and every memory operand form. - Instructions: every mnemonic in twelve groups, with its forms, its flags and what the viewer shows.
- Opcode maps: the first-byte map and the second-byte map of each operand class.
- Status: documented, reserved and illegal encodings, the differences found between our reading of the manual and the RACE core, and what is not described.
How an instruction is built
| First byte | Meaning | Length |
|---|---|---|
$00–$7F | A complete instruction: control (NOP, HALT, EI…), loads of immediates, PUSH and POP of a register, JP, CALL, CALR, JR cc, JRL cc | 1 to 5 |
$80–$BF | A memory operand ((XWA) … (XSP), or with an 8-bit displacement) for a byte, word, long or destination/address instruction, then a second byte | 2 to 7 |
$C0–$F5 | A memory operand (8, 16 or 24-bit absolute, a complex form, a pre-decrement, a post-increment) or a register ($C7, $C8–$CF and the same for word and long), then a second byte | 2 to 7 |
$F7 | LDX: a store of a byte to an 8-bit address, written in six bytes | 6 |
$F8–$FF | SWI 0 to SWI 7 | 1 |
Example, from the Snake homebrew ROM: F2 40 00 20 34 is LDA XIX,($200040) (F2: a destination operand with a 24-bit address, then second byte $34: LDA into the long register 4, XIX);
E5 F2 20 is LD XWA,(XIX+) (E5: a long operand, post-increment, register code $F2 = XIX with step code 2, i.e. 4 bytes; then $20: LD into long register 0).
Statuses in the viewer
- documented: an encoding the TLCS-900/H manual defines (as far as we could establish; see the not-described list).
- reserved: the bytes decode, but the manual defines the instruction with another prefix or register code (
LDIRwith a prefix other than$83or$85, a register code that names no register). - illegal: an undefined encoding. The CPU takes the illegal-instruction trap; the viewer shows one
.BYTEand decodes the next byte on its own.
See Status for the list.
How this was checked
- The RACE core. RACE (“Rather A Cardfighter Emulator”, GPL, libretro) is a Neo Geo Pocket emulator with a hand-written TLCS-900/H core; it runs here as WebAssembly. The decoder’s definedness matches RACE’s own dispatch tables for all 256 first bytes and 39,424 combinations of prefix, operand form and second byte; the same encodings were then run in RACE from random register and memory states and the length, the registers, flags and memory it changed were compared with what the decoder declares.
- Real code. The two public-domain homebrew ROMs Snake and Fractal were run for 400,000 instructions each in RACE; each executed instruction was decoded from the bytes at the PC and the next PC had to be the one the decoder predicts.
- Written tables. A second table of the instruction set, written separately from the decoder’s, is compared mnemonic by mnemonic (same author: it catches slips, not misreadings of the manual).
- No TLCS-900/H assembler, disassembler or second emulator was found on this machine, and the Toshiba manual could not be read in full (see Not described). The one-line semantics, the flag effects and the register-code tables rest on our reading of the manual as remembered and on RACE; the places where they disagree are listed on the status page.
Sources
- RACE for libretro (
tlcs900h.c) – the core the decoder is checked against - TMP95C061 data sheet – Toshiba, on bitsavers (named, not read in full)
Not described
See the list on the status page: no cycle counts, the TLCS-900/L is not covered, and the manual itself could not be read here.