Welcome at the cfx 9850 G hacking page !
Here you can find all information about CPU of this calculator (instruction codes, subroutine adresses,...) I found.
I don`t know the manufacturer or the type of CPU used, so all, what you read here, I found in a lots of hours of hacking, disassembling and hacking....
General about CPU
Address : 16 bits, special unconditional long jump 24 bits
Data : 8,16 and variable length from 8 to 128 bits, step 8 bits selectable in runtime (also instructions working with RAM)
Registers: array of 128 8 bit registers which can be used as single registers or grouped to any supported size (8 - 128 bits)
Size of segment : 64 KB (16 bit addressing)
More segments : read this
The far jump instruction is used very very few times in the whole ROM
Memories
20h..27h : ROM - 8 segments (8x 64 KB = 512 KB), segs 0 - 3 code, 3 - 5 data, 6-7 unused :-))
40h : RAM - 1 segment (32 KB), upgradeable to 64 KB and probably to 512 KB :-))) (not tested),
8h : VIDEO - 1 segment (2 KB) - CPU stack at 02FF and buffers for text screens
60h: Display RAM - 1 segment (8KB), used as graphic display - ((2 color rows)
* (128 columns) * (64 rows) bits)
this segment is NEVER only once in the whole ROM ccessed
by DSeg 60h, in all other cases by Dseg R3F
Table of Instructions
:-) | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF |
0x | shrB R,8 | shrW R,8 | shr8 R,8 | shr10 R,8 | maskB | maskW | mask8 | mask10 | shlB R,4 | shlW R,4 | shl8 R,4 | shl10 R,4 | TestB | TestW | Test8 | Test10 |
1x | xorB | xorW | xor8 | xor10 | cmpB | cmpW | cmp8 | cmp10 | movB | movW | mov8 | mov10 | nmaskB | nmaskW | nmask8 | nmask10 |
2x | shrB | shrW | shr8 | shr10 | orB | orW | or8 | or10 | shlB | shlW | shl8 | shl10 | andB | andW | and8 | and10 |
3x | BsubB | BsubW | Bsub8 | Bsub10 | subB | subW | sub8 | sub10 | BaddB | BaddW | Badd8 | Badd10 | addB | addW | add8 | add10 |
4x | shrB [R],8 | shrW [R],8 | shr8 [R],8 | shr10 [R],8 | maskB[] | maskW[] | mask8[] | mask10[] | shlB [R],4 | shlW [R],4 | shl8 [R],4 | shl10 [R],4 | TestB[] | TestW[] | Test8 [] | Test10[] |
5x | xorB[] | xorW[] | xor8[] | xor10[] | cmpB[] | cmpW[] | cmp8[] | cmp10[] | movB[] | movW[] | mov8[] | mov10[] | nmaskB[] | nmaskW[] | nmask8[] | nmask10[] |
6x | shrB[] | shrW[] | shr8[] | shr10[] | orB[] | orW[] | or8[] | or10[] | shlB[] | shlW[] | shl8[] | shl10[] | andB[] | andW[] | and8[] | and10[] |
7x | BsubB[] | BsubW[] | Bsub8[] | Bsub10[] | subB[] | subW[] | sub8[] | sub10[] | BaddB[] | BaddW[] | Badd8[] | Badd10[] | addB[] | addW[] | add8[] | add10[] |
8x | 1 | 1 | jump | jumpf | call | 1 | 1 | 1 | ||||||||
9x | rzh | rzl | rc | rz | rzc | rcl | rnc | rnz | jump[] | iret | ret | |||||
Ax | jzh | jzl | jc | jz | jzc | jcl | jnc | jnz | callzh | callzzl | callc | callz | callzc | callcl | callnc | callnz |
Bx | ||||||||||||||||
Cx | 3 | movW16 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | |||||
Dx | Cseg R | Cseg | 2 | 2 | Sseg R | Sseg | SReg R | SReg | SFlag R | SFlag | Dseg R | Dseg | ||||
Ex | 2 | 2 | 2 | 2 | 2 | LD TIME | 2 | 2 | LD NXA1 | LD NXA2 | LD IP | LD SBP | 2 | LD DSEG | LD CSEG | LD SSEG |
Fx | 2 | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 1 | 1 | 1 | nop |
:-) | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF |
<n> = unknown instruction, but it's length is probably n B
<?n> = unknown instruction, unknown length, but probably length = n B
Nothing
FF nop ; used for filling free space
Jumps and calls
Parameter: target address - 16 bit - big endian
88 jump
89 jumpf - far jump, first parameter is number of target segment, the second
and third p. are
offset - big endian
8A call
A1 unknown (conditional) jump
A2 jc ;jump if carry
A3 jz ;jump if zero
A4 jzc ;jump if carry or zero
A6 jnc ;jump if not carry
A7 jnz ;jump if not zero
AA callc ;call if carry
AB callz ;call if zero
AC callzc ;call if zero or carry
AE callnc ;call if not carry
AF callnz ;call if not zero
Example: 88 12 34 Jump 1234
98 jump <register> : jump to the address stored in the register, it must be big endian, but data are loaded in little endian, so jump to the address 1234 is done
C1 75 34 12 ;mov R75 1234
98 76 ; jump[R76] - it reads the register "backwards"
Returns from subroutines
No parameter
9F ret ;unconditional return
92 retc; return if carry
93 retz ; return if zero
94 retzc ;return if zero or carry
96 retnc ;return if not carry
97 retnz ;return if not zero
Segment change
Parameter - number of segment or register containing the number of segment - 8 bit
D1 CSeg ;change code segment - number
DC DSeg ;change data segment - register
DD DSeg ;change data segment - number
Example: D1 22 Cseg 22 (skip to the second segment in ROM)
Value (HEX) | Segment description |
00 | Some internal ROM (probably stored in the CPU) |
08 | VIDEO RAM - buffer for text output, stack |
20 <-> 27 | ROM segment 0 <-> ROM segment 7 (8x64KB = 512 KB) |
40 | RAM segment 0 |
41 <-> 47 | No device, here should be placed additional RAM (upgrade to 512 KB) |
60 | Graphic memory - display bitmap |
Register and register/value arithmetic operation
Data Length
The last character(s) of instruction name is data length:
B: byte = 8 bits
W: word = 16 bits
8: variable data length X, in most cases it's running in 64 b mode, so I used the length in B
10:variable data length Y, in most cases it's running in 80 b mode, so I used the length in B
If the instruction name starts with "B", this instruction is working in BCD mode, in this mode only digits 0..9 are allowed , one digit is stored using 4 bits. So you can store only numbers 0 .. 99 to 1 byte.
Addressing modes
There is a few addressing modes:
reg-reg/reg-val mode: B1 B2 B3 -used by xor,cmp,mov,or,and,sub,add,mask,nmask - see the first 4 rows.
B1: operation code
B2: lower 7 bits - number of the first register, the highest bit says, if B3 is direct value (1) or another register (0).
B3: direct value (B2&128=128) or lower 7 bits is number of the second register, the highest bit probably says, which register is used to store result (1- 1st reg, 0-2nd reg)
mem-reg/mem-val mode: B1 B2 B3 -used by cmp,mov,or,and,sub, and ,add - see the second 4 rows.
B1: operation code
B2: lower 7 bits - number of the address register, the highest bit says, if B3 is direct value (1) or register (0).
B3: direct value (B2&128=128) or lower 7 bits is number of the second register, the highest bit says, where should be result stored (1- back to memory, 0-to register)
1 register only mode: B1 B2 - used by "shr <R>,8", "rol <R>,4", shl,shr
B1: operation code
B2: lower 7 bits - number of the register
Note: rol is working through some 4 bits (may be flags)
Load 16bit value to the word register
C1 <register> <data.lo> <data.hi>
Other
Other instructions are unknown for me now. I will be happy if you help me to find them.