This page's trying to cover SC-61860's machine language used on most Sharp pocket computers (series PC-12??, PC-13??, PC-14?? and PC-2500)
Some french words :
Cette page est uniquement en anglais car je n'ai
le temps de créer qu'une seule
documentation, et puis, je fais beaucoup moins de fautes dans la langue de Shakespear. L'anglais n'est pas très
recherché (car c'est le mien ;-D).
Please note : in this page
&xx
stands for 8 bits
hexadecimal values,
&xxxx
a 16 bits
hexadecimal value or external RAM address,
$xx
means for an
internal RAM 8 bits address.
The SC-61860 is a 8 bits CPU based on CMOS
technology used by most 80' Sharp Pocket computer :
PC-12??, 13?? and 14??. PC-15??, PC-1600 and all 4
bits powered pocket are excluded.
In fact this CPU should really called a 'Micro
Controller' as it contains also some part of
the LCD drivers (it's why it has so many pins).
It has also 8k of ROM embedded, named the
"internal ROM", which is different
between PC models, and 96 bytes internal
memory. Notez bien : the internal ram is very very
faster than the external one. Using this memory save
lof of CPU cycles, and as the system clock is very slow,
it will improve noticeably critical stuffs.
|
|
|
IX
, DX
, IXL
, DXL
, IY
, DY
, IYS
, DYS
).
CLA
(&23) should be called LDS
).
(dp)
is not the register d).
|
indexes is the official name of these registers
but, in fact they are used mainly for repeated
instructions. J is always set to '1' so
instructions using this register are almost used for
16 bits manipulations (EXBD , ...?).
|
|
Even if all bytes of the internal memory should be considered as a 'general use register', K,L,M,N have some special instructions to use them : INC? and DEC? .Please also note that many mnemonics have 'M' in there names. It stand for (P) , only INCM and DECM use directly the M register.
|
bits | Connector | Pine # | I/O | Name : sharp (standard) |
---|---|---|---|---|
0 | SIO | 14 | O | ER (DTR) |
1 | SIO | 4 | O | RS (RTS) |
2 | SIO | 11 | O | RR (DSR) |
3 | SIO | 3 | I | RD (RxD) |
4 | SIO | 5 | I | CS (CTS) |
5 | SIO | 8 | I | CD (CD) |
6 | SD | 8 | I | Din |
7 | SD | 9 | I | Ack |
bits | Connector | Pine # | I/O | Name : sharp (standard) |
---|---|---|---|---|
0 | n/a | n/a | Memory protected the memory can't be read, always return the upper byte of it own address : LIDP &253f; LDD -> &25
| |
1 | SD | 4 | O | Busy |
2 | SD | 5 | O | Dout |
bits | Name | Comment # |
---|---|---|
0 | Display | Display ON (1)/OFF (0) |
1 | Reset | Reset counter (see TEST ) |
2 | HLT | Stop the CPU (wake up when the 512ms counter rise) |
3 | OFF | Power off the machine |
4 | BZ1 | Signal High |
5 | BZ2 | Sound activated |
6 | BZ3 | Xin activated |
Some instructions can compute BCD numbers but, unlike mathematical processing unit of moderns CPU, they use normals registers in the "internal working memory".
So, in this memory, some groups of 8 bytes are commonly used for BCD computation by ROM functions :
This memory hold temporary objects :
The stack start at $5b and increases downward. In fact, there is no real limit on stack expention and no check is done.
Unlike most other systems, the CPU stack is not intensively used.
For exemple, on 68000 systems, stacks are used to reserve working area, to pass parameters between functions, to store scrach registers and to store program environment when an interruption occurs, ...
On SC61860's machine this stack is only used to stock return address of sub routines and eventually, to save some registers. And as this CPU doesn't have any interrupts capability, a very small stack is enough.
LIr n
: r <- #n
LII n
(&00), LIJ n
(&01), LIA n
(&02), LIB n
(&03),
LIP n
(&12), LIQ n
(&13)
LIDP nn
(&10), LIDL n
(&11)
For small values, LIP n
can be shorted by LP n
, coded in only one byte (LP 3F
- &80 - to LP 3F
- &BF -)
LDr
: A <- r
LDP
(&20),
LDQ
(&21),
LDR
(&22),
and
LDD
(&57) : A <- (DP)
LDM
(&59) : A <- (P)
STr
: r <- A
STP
(&30),
STQ
(&31),
STR
(&32),
and
STD
(&52) : (DP) <- A
Please note : STM
doesn't exist. Use EXAM
instead.
MVW
(&08) : [(P++) <- (Q++)] * I
MVB
(&0A) : [(P++) <- (Q++)] * J
(as J is usualy 1, perfect for 16 bits move)
MVWD
(&18) : [(P++) <- (DP++)] * I
MVBD
(&1A) : [(P++) <- (DP++)] * J
(as J is usualy 1, perfect for 16 bits move)
MVDM
(&53) : (DP) <- (P)
MVMD
(&55) : (P) <- (DP)
DATA
(&35) : [(P++) <- ({B,A}++);] * I
This instruction is the ONLY ONE for reading protected memory (i.e. first 8k ROM).
EXW
(&09) : [(P++) <-> (Q++)] * I
EXB
(&0B) : [(P++) <-> (Q++)] * J
(as J is usualy 1, perfect for 16 bits move)
EXWD
(&19) : [(P++) <-> (DP++)] * I
EXBD
(&1B) : [(P++) <-> (DP++)] * J
(as J is usualy 1, perfect for 16 bits move)
EXAB
: A <-> B
(&DA)
EXAM
: A <- (P)
(&DB)
INCr
: r <- r+1
DECr
: r <- r-1
INCP
and DECP
don't modify anything but P).
INCI
(&40),
DECI
(&41),
INCJ
(&C0),
DECJ
(&C1),
INCA
(&42),
DECA
(&43),
INCB
(&C2),
DECB
(&C3),
INCK
(&48),
DECK
(&49),
INCL
(&C8),
DECL
(&C9),
INCM
(&4A),
DECM
(&4B),
INCN
(&CA),
DECN
(&CB),
INCP
(&50),
DECP
(&51)
Ir
: r <- r+1; DP <- r
Dr
: r <- r-1; DP <- r
IX
(&04),
DX
(&05),
IY
(&06),
DY
(&07),
X and Y registers allow blocs memory moves using following instructions :
IXL
(&24): X <- X+1; DP <- X; A <- (DP)
DXL
(&25): X <- X-1; DP <- X; A <- (DP)
IYS
(&26): Y <- Y+1; DP <- Y; (DP) <- A
DYS
(&27): Y <- Y-1; DP <- Y; (DP) <- A
So the following listing are equivalent
Normal listing | Optimized listing |
{start_loop} IX LDD IY STD DECI JRNZ {start_loop} |
{start_loop} IXL IYS DECI JRNZ {start_loop} |
---|
Adding | Subtracting | ||||
---|---|---|---|---|---|
Binary | |||||
|
|
code | AN Logical AND | OR Logical OR | TS Test | CP Compare |
opIA n A <- A op #n
| &64 | &65 | &66 | &67 |
opIM n (P) <- (P) op #n
| &60 | &61 | &62 | &63 |
opID n (P) <- (P) op #n
| &D4 | &D5 | &D6 | &D7 |
opMA n (P) <- (P) op #n
| &46 | &47 | &C6 | &C7 |
for all operations,
Z=1 if the result is null or Z=0 otherwise.
C is only affected by an CP instuction.
|
| |||||||||||||||
|
JRP n
(&2C): PC <- PC + #n
JRM n
(&2D): PC <- PC - #n
JP nn
(&79): PC <- #nn
For relative jump, JRP
and JRM
, the reference is the address of the argument. So
JRP 01
does nothing.JRM 01
is an infinit loop to itself.
JRcP n
, JRcM n
, JPc nn
does the same thing but with a condition :
|
|
CALL nn
(&78): (R-1,R) <- PC; R <- R-2; PC <- #nn
RTN
(&37): PC <- (R-1,R); R <- R+2
CALL
saves the current PC value and jump to a sub routine. RTN
ends this sub routine and returns to the saved PC value (PC is now on the instruction following the CALL
).
CAL 00 n
(&E0) to CAL 1F n
(&E0) does the same thing but saves one byte and some CPU cycle and are reserved for function in the first 8k memorie (the internal ROM).
CASE1 nb rtn@dr
CASE2 val1 @dr1 val2 @dr2 ... valn @drn def@dr
Using theses instructions, it is very very easy to call a sub routine associated to a value of A (same as
|
|
PUSH
(&34): (R) <- A; R <- R-1
POP
(&5B): A <- (R); R <- R+1
LOOP n
(&2F): (R) <- (R)-1; if c=0 then PC <- PC + 1 - #n else PC <- PC + 2; R <- R+1
LEAVE
(&D8): (R) <- 0
With these instructions, a loop can be easily made, and LEAVE
is an easy way to exit from a loop.
How to use LOOP |
|
LIA 5 PUSH LIB 0 {lbl} INCB LOOP {lbl} LIDP &6c30 EXAB STD RTN |
02 05 34 03 00 C2 2F 03 10 6C 30 DA 52 37 |
(&6C30) => 6 |
---|
INA (&4C): A <- PortA OUTA (&5D): PortA <- ($5c)
|
INB (&CC): A <- PortB OUTB (&5D): PortB <- ($5d)
|
OUTF (&5F): PortF <- ($5e) OUTC (&DF): PortC <- ($5f)
|
FILM
(&1E): [(P) <- A; P++] * I
FILD
(&1F): [(DP) <- A; DP++] * I
SL (&5A): Shift A leftSR (&5D): Shift A Right
|
|
SLW
(&1D): Shift 4 bits left starting P and on I bytes.([SHIFT4LEFT(P); P <- P-1] * I
)
SRW
(&1C): Shift 4 bits right starting P and on I bytes.([SHIFT4RIGHT(P); P <- P+1] * I
)
WAIT n
(&4E): Wait 6 + n cyclesNOPW
(&4D): Wait 2 cyclesNOPT
(&CE): Wait 3 cyclesCUP
(&4F): Wait if xin is not highCDN
(&6F): Wait if xin is not low
d <- I; repeat d--; until (d==&ff or Xin=condition);
TEST n
(&6B)
This instruction acts as if we TS
a system port of the CPU.
|
|
SWP
(&58): Swap A7-4, A3-0
(LIA &ab; SWP
=> A=&ba).
SC
(&D0): C=1, Z=1
RC
(&D1): C=0, Z=1
Hum, I realy don't know what should be the useness of such instructions ;-D
READ
(&56): A <- (PC + 1)
READM
(&54): (P) <- (PC + 1)
WRIT
(&D3): ????