MN1610の後継として1981年に発表されたものがMN1613です。MN1610の上位互換で、メモリ空間を拡張し演算の高速化を実現したものです。クロックはMN1610が2
MHzだったものを13.3 MHzとし、命令の先読みを行うようにしたため、レジスタ間演算が最短0.3
usで行えるようになりました(MN1610では3 us)。メモリ空間はセグメントレジスタを併用した拡張がなされ、トータルで256
KWordになっています。
MN1613とMN1613A。上のMN1613は40 pinですが、下のMN1613Aは42 pinパッケージです。単に高速化されたものではなく、ピン数まで異なるとは。簡単なテストから得た想像ですが、MN1613Aは1番と42番ピン以外の40本がMN1613と共通で、その2本は何らかの出力専用端子のようでした。
上から見ると、変哲のないセラミックパッケージですね。ところで、このMN1613やMN1613Aをひっくり返してみると、こんなです。この金属板はヒートスプレッダか何かだと思いますが、実際のところはどうなのでしょうか。なお、PFL-16AシリーズのMN1613以外の石の裏面は、普通のセラミックだけのパッケージです。
MN1613の裏面。
MN1613はMN1610とバイナリ上位互換です。リセット直後の動作など特別なところを除けば、MN1610のコードがそのまま動作します。また、ハードウエア面でもそれなりの互換性があり、入出力デバイスなどはそのまま接続することもできます。ただし、メモリ拡張用のセグメントレジスタなど特殊レジスタが追加され、クロックジェネレータやインターバルタイマなどMN1640の機能の一部が内蔵され、MN1610の未定義命令を拡張し2語命令も許容することによって32 bit浮動小数点演算を含む命令の拡張が行われています。アドレッシングモードも拡張されたアドレス空間を利用しやすくするため強化されていますが、追加されたアドレッシングモードを利用する命令は従来のものとは別命令扱いになっていることもあって、MN1610では33種の基本命令が97種にまで、およそ3倍に増やされています。また、コンソールパネル機能の実現方法もMN1610とは異なり、コンソールパネル機能を実現するプログラムを特殊なアドレス空間に配置できるようになっています。
内蔵しているレジスタ類は、このようになっています。
網掛け部は未使用ビットで、常に0が入っています。
図の中で赤枠で囲っている汎用レジスタ・命令カウンタはMN1610と共通の部分です。MN1610には赤枠内のレジスタしか存在しませんでした。ただし、命令の拡張に応じて、R1,
R2, R3, R4が特別なアドレッシングモードに利用されたり、R0とR1が連結されて32
bit整数や浮動小数点用のアキュムレータDR0として利用されるなど、MN1610にはなかった特別な機能も加わっています。
セグメントベースレジスタは、略してベースレジスタと呼ばれることもありますが、アドレス拡張用のレジスタで、用途により4種類ありますが、それぞれ4
bit幅です。MN1613の物理アドレスは、基本的にはMN1610と同じか拡張されたアドレッシングモードで求められた16
bit論理アドレスに、このセグメントベースレジスタの内容を14 bit左シフトして加算して求めます。加算の際の桁上がりは無視され、最終的に得られる物理アドレスは18
bit幅となります。
Current Segment Base Registor (CSBR)は一般の命令実行に関して利用されるベースレジスタです。Stack
Segment Base Register (SSBR)はサブルーチン呼び出しやスタックへのPush/Popのようなスタック参照時に使用されるベースレジスタです。ブロック転送命令など特別な命令の実行時に使用されるのがTemporary
Segment Base Register 0, 1であるTSR0とTSR1です。普通はCSBR、ただしスタック領域だけはSSBRが使用されると理解しておけば、ほぼ問題ないでしょう。マルチタスクモニタで複数のタスクを並行動作させる場合、特権モードの類はありませんから完全なメモリ保護はできませんが、複数のタスク間でのゼロページ領域の干渉や不足がMN1610で問題になりますが、CSBRによって個別のタスクごとに固有のゼロページ領域(とその他の領域)を持たせることができます。
割り込み時には、CSBRの内容が割り込みレベルに対応したベース退避レジスタにコピーされ、その後にCSBRの内容が0クリアされてMN1610と同様の割り込みシーケンスが始まります。つまり、割り込みサービスルーチンが物理アドレス空間の先頭64
KWord内に存在する必要がある以外はMN1610と互換性を持つようになっています。割り込みレベルは0から2までなので、OSRは0から2までしか必要ないはずですが、OSR3も用意されていてソフトウェア的に利用できます。
特殊レジスタのうちNew Program Status Word Pointer (NPP)は、他のマイクロプロセッサの割り込みベクタ領域に相当するNPSWの先頭アドレスを指示するポインタで、上位8
bitだけが有効です。NPSWを読み出すときにはCSBRは0クリアされているので、先頭64
KWord内の256 Word境界にNPSW領域を割り当てることが可能です。リセット時には1が入るので、MN1610と互換性があります。
Internal Interrupt Status Register (IISR)は未定義命令が実行されレベル0の割り込みが発生したことを通知するためのレジスタで、該当条件が成立した場合に1がセットされます。
CSBR Buffer (SBRB)とIC Buffer (ICB)はコンソール処理プログラムからのみ利用できるレジスタで、プロセッサがコンソール処理プログラムの実行を開始する直前のCSBRとICがそれぞれSBRBとICBにコピーされ、逆に通常の実行状態に遷移する際にはSBRBとICBの内容がそれぞれCSBRとICにコピーされます。
MN1613にはMN1640に内蔵されていたのと似ているインターバルタイマ機能が内蔵されていて、その制御を行うのがタイマレジスタです。また、単純なシフトレジスタを用いたシリアル入出力機能も内蔵されていて、その制御用のレジスタが直列入出力レジスタです。
アドレッシングモードはMN1610と共通のものに、さらに数種類追加されています。MN1613はMN1610とバイナリ互換がありますから、MN1610と共通の命令ではまったく同じアドレッシングモードが使えます。追加されたアドレッシングモードを使う命令は、すべて専用のMN1613に新設された命令で、アセンブリ言語レベルでもニーモニックから異なります。ただし、MN1610と共通のアドレッシングモードにおいては、スタックアクセスを除き、CSBRの内容が14
bit左シフトして加算されることが異なります。スタックアクセスの場合にはSSBRがセグメントベースレジスタとして使われます。
追加されているアドレッシングモードは以下の6種です。
以下に全命令の一覧を示します。
意味
アセンブリ言語表記
Load
L R, Addr
Load Direct
*LD R[, BRn], Exp
Load Register Indirect
*LR R[, BRn], {(Ri) | (Ri)+ | -(Ri)}
Store
ST R, Addr
Store Direct
*STD R[, BRn], Exp
Store Register Indirect
*STR R[, BRn], {(Ri) | (Ri)+ | -(Ri)}
Move
MV Rd, Rs[, Skip]
Move Word Register Indirect
*MVWR R0, (Ri)[, Skip]
Move Word Immediate
*MVWI Rd, Exp[, Skip]
Move Byte
MVB Rd, Rs[, Skip]
Move Byte Register Indirect
*MVBR R0, (Ri)[, Skip]
Byte Swap
BSWP Rd, Rs[, Skip]
Byte Swap Register Indirect
*BSWR R0, (Ri)[, Skip]
Digit Swap
DSWP Rd, Rs[, Skip]
Digit Swap Register Indirect *DSWR
R0, (Ri)[, Skip]
Push
PUSH R
Push Multi
*PSHM
Pop
POP R
Pop Multi
*POPM
Move Immediate
MVI R, Exp
Add
A Rd, Rs[, Skip]
Add Word Register Indirect
*AWR R0, (Ri)[, Skip]
Add Word Immediate
*AWI Rd, Exp[, Skip]
Add Immediate
AI R, Exp[, Skip]
Subtract
S Rd, Rs[, Skip]
Subtract Word Register Indirect *SWR R0,
(Ri)[, Skip]
Subtract Word Immediate
*SWI Rd, Exp[, Skip]
Subtract Immediate
SI R, Exp[, Skip]
Compare
C Rd, Rs[, Skip]
Compare Word Register Indirect *CWR
R0, (Ri)[, Skip]
Compare Word Immediate
*CWI Rd, Exp[, Skip]
Compare Byte
CB Rd, Rs[, Skip]
Compare Byte Register Indirect *CBR
R0, (Ri)[, Skip]
Compare Byte Immediate
*CBI Rd, Exp[, Skip]
Nagate with Carry
*NEG Rd[, C][, Skip]
Add Double with Carry
*AD DR0, (Ri)[, C][, Skip]
Subtract Double with Carry
*SD DR0, (Ri)[, C][, Skip]
Multiply
*M DR0, (Ri)[, Skip]
Divide
*D DR0, (Ri)[, Skip]
Decimal Adjust
Addition with Carry
*DAA R0, (Ri)[, C][, Skip]
Decimal Adjust
Subtraction with Carry
*DAS R0, (Ri)[, C][, Skip]
Load Adjust Part
LAD Rd, Rs[, Skip]
Load Adjust Part
Register Indirect
*LADR R0, (Ri)[, Skip]
Load Adjust Part Immediate
*LADI Rd, Exp[, Skip]
Floating Add
*FA DR0, (Ri)[, Skip]
Floating Subtract
*FS DR0, (Ri)[, Skip]
Floating Multiply
*FM DR0, (Ri)[, Skip]
Floating Divide
*FD DR0, (Ri)[, Skip]
Fix
*FIX R0, DR0[, Skip]
Float
*FLT DR0, R0[, Skip]
Logical And
AND Rd, Rs[, Skip]
Logical And Register Indirect *ANDR
R0, (Ri)[, Skip]
And Immediate
*ANDI Rd, Exp[, Skip]
Inclusive Or
OR Rd, Rs[, Skip]
Inclusive Or Register Indirect *ORR
R0, (Ri)[, Skip]
Inclusive Or Immediate
*ORI Rd, Exp[, Skip]
Exclusive Or
EOR Rd, Rs[, Skip]
Exclusive Or Register Indirect *EORR R0,
(Ri)[, Skip]
Exclusive Or Immediate
*EORI Rd, Exp[, Skip]
Increment Memory
and Skip if Result is Zero
IMS Addr
Decrement Memory
and Skip if Result is Zero
DMS Addr
Branch
B Addr
Branch Direct
*BD Exp
Branch Long
*BL (Exp)
Branch Register Indirect
*BR (Ri)
Branch and Link
BAL Addr
Branch and Link Direct
*BALD Exp
Branch and Link Long
*BALL (Exp)
Branch and Link Register Indirect *BALR (Ri)
Return
RET
Return Long
*RETL
Load Program Status Word
LPSW
Test Bit
TBIT R, Exp[, Skip]
Set Bit
SBIT R, Exp[, Skip]
Reset Bit
RBIT R, Exp[, Skip]
Test and Set
*TSET Rs, Exp[, Skip]
Test and Reset
*RSET Rs, Exp[, Skip]
Search Bit Position
*SRBT R0, Rs
Decode Bit Position
*DEBP Rd, R0
Shift Right 1 bit
SR R[, Set][, Skip]
Shift Left 1 bit
SL R[, Set][, Skip]
Move Data Block
*BLK (R2), (R1), R0
Read
RD R, Exp
Read Register Indirect
*RDR R, (Ri)
Write
WT Rs, Exp
Write Register Indirect
*WTR R, (Ri)
Load Base Register
*LB BRd, Exp
Load Special Register
*LS SRd, Exp
Store Base Register
*STB BRs, Exp
Store Special Register
*STS SRs, Exp
Copy Base Register
*CPYB Rd, BRs
Copy Special Register
*CPYS Rd, SRs
Copy Hardware Control Register *CPYH Rd,
HRs
Set Base Register
*SETB Rs, BRd
Set Special Register
*SETS Rs, SRd
Set Hardware Register
*SETH Rs, HRd
Halt
H
アセンブリ言語表記で、[]内は省略可能であることを示します。スキップ条件、Eレジスタ操作、キャリー操作が省略可能です。また、{}内で|をデリミタとして並べた項目は、その中のどれかひとつを選択できることを意味します。ポストインクリメント間接およびプリデクリメント間接指定が選べるところに使われています。また、ニーモニックの先頭に*が付けられている命令は、MN1613で新設された命令です。付けられていないものはMN1610と互換であることを意味します。
オペランド部分で、AddrはMN1610と共通のアドレッシングモードを記入することを意味します。Expは数式を意味し、定数、セグメント内16
bitアドレスなどに使われています。Rはレジスタ、BRはベースレジスタ、Riは間接アドレス用レジスタ、SRは特殊レジスタ、HRはハードウエア制御レジスタを意味します。レジスタのポストフィックスとして使われているsはソースレジスタを、dはディスティネーションレジスタを意味します。
レジスタ間接アドレッシング系の命令の大部分は、一方のオペランドとしてR0かDR0だけが使用可能で、一種のアキュムレータとして利用されていることがわかります。
16 bit整数演算命令にはレジスタ間接アドレッシングのほか、イミディエートモードができて便利になりました。MN1610ではルーチンの切れ目に定数置き場を作って、直接相対で参照するしかありませんでしたから。
乗除算および浮動小数点演算はレジスタ間接アドレッシングのものばかりです。これらの命令にもスキップ条件を付けられるのは、ちょっと驚きです。命令実行時間は乗算命令が8.4
us、除算命令が17.4 us、浮動小数点加算が15.6 - 22.8 us、浮動小数点減算が16.2
- 24.0 us、浮動小数点乗算が52.2 - 58.2 us、浮動小数点除算が73.5 - 88.5
usとなっています。内蔵のマイクロプログラムで処理するので、これくらい必要なのはわかるのですが、この命令実行時間の間は割り込みを受け付けられないはずです。MN1610と比べて、割り込みルーチンの最短応答時間は悪くなっていますね。
分岐命令にはセグメントレジスタも同時に変更するものが追加されています。サブルーチン呼び出しも同じで、セグメントと16
bitアドレスをスタックにプッシュするものが追加され、それに対応したリターン命令も新設されています。
ビット操作では、マルチプロセッサ用、あるいは単一プロセッサでもセマフォの実装用に便利な命令が追加されたほか、グラフィックス表示関係で便利なこともある命令が追加されています。
BLK命令はブロック転送で、R0の内容で示された語数のデータを転送します。セグメント間転送も可能ですし、命令実行途中に割り込みを受け付けることもできます。
入出力命令にはレジスタ間接アドレッシングが可能なものが新設されました。この命令では、16
bit I/Oアドレス空間を扱うことができます。従来の入出力命令では、上位8 bitが0に固定された256語分のI/O空間だけをアクセスできます。
それ以降は内蔵の新しいレジスタを参照するための命令です。
データ転送系の命令から詳細を見ていきます。
命令 オペコード
2語目 EV 動作
L 11MMM RRR dddd dddd
R <- (EA)
LD 00100 111 00BB 1RRR AD16
R <- (EA)
LR 00100 RRR mmBB 00ii
R <- ((Ri)), modify indirect register
ST 10MMM RRR dddd dddd
EA <- (R)
STD 00100 111 01BB 1RRR AD16
EA <- (R)
STR 00100 RRR mmBB 01ii
(Ri) <- (R), modify indirect register
MV 01111 ddd kkkk 1sss
Rd <- (Rs), skip
MVWR 01111 111 kkkk 10ii
R0 <- ((Ri)), skip
MVWI 01111 ddd kkkk 1111 IM16
Rd <- IM, skip
MVB 01111 ddd kkkk 0sss
Rd_L <- (Rs)_L, skip
MVBR 01111 111 kkkk 00ii
R0_L <- ((Ri))_L, skip
BSWP 01110 ddd kkkk 1sss
Rd_L <- (Rs)_U, Rd_U <- (RS)_L, skip
BSWR 01110 111 kkkk 10ii
R0_L <- ((Ri))_U, R0_U <- ((Ri))_L, skip
DSWP 01110 ddd kkkk 0sss
Rd <- digit swap(Rs), skip
DSWR 01110 111 kkkk 00ii
Rd <- digit swap((Ri)), skip
PUSH 00100 RRR 0000 0001
(SP--) <- (R)
PSHM 00010 111 0000 1111
(SP--) <- (R0) (R1) (R2) (R3) (R4)
POP 00100 RRR 0000 0010
R <- ((++SP))
POPM 00010 111 0000 0111
R4 R3 R2 R1 R0 <- ((++SP))
MVI 00001 RRR dddd dddd
R_L <- IM8
オペコード部分は2進数表示です。MN1613のオペコードのフィールドに応じて、5,
3, 4, 4 bitのグループに分けています。MMM, RRR, dddddddd, BB, mm, ii, ddd,
sss, kkkkには、それぞれ次の表の意味があります。
MMMとddddddddの意味
MMM | ddddddddの意味 | モード | 実効論理アドレス |
000 | 無符号整数D | ゼロページ直接 | D |
001 | 符号付き整数d | 相対 | (IC) + d |
010 | 無符号整数D | ゼロページ間接 | [D] |
011 | 符号付き整数d | 相対間接 | [(IC) + d] |
100 | 無符号整数D | 直接インデックス0 | (X0) + D |
101 | 無符号整数D | 直接インデックス1 | (X1) + D |
110 | 無符号整数D | 間接インデックス0 | (X0) + [D] |
111 | 無符号整数D | 間接インデックス1 | (X1) + [D] |
RRR, ddd, sssは汎用レジスタを意味するフィールドです。
RRR, ddd, sss | レジスタ |
000 | R0 |
001 | R1 |
010 | R2 |
011 | R3またはX0 |
100 | R4またはX1 |
101 | SP |
110 | STR(L, LD, L, ST, STD, STR, RDR, WTR命令では禁止) |
111 | 禁止 |
BBはセグメントベースレジスタを意味するフィールドです。
BB | セグメントベースレジスタ |
00 | CSBR |
01 | SSBR |
10 | TSR0 |
11 | TSR1 |
mmは間接レジスタに関する動作モードを指定するフィールドです。
mm | 動作モード |
01 | (Ri) |
10 | -(Ri) |
11 | (Ri)+ |
iiは間接レジスタを指定するフィールドです。
ii | 間接レジスタ |
00 | R1 |
01 | R2 |
10 | R3 |
11 | R4 |
kkkkはスキップ条件を指定するフィールドです。
kkkk | 記号 | 意味 |
0000 | -- | スキップせず |
0001 | SKP | 無条件スキップ |
0010 | M | 結果が負 |
0011 | PZ | 結果が正または零 |
0100 | ZまたはE | 結果が零 |
0101 | NZまたはNE | 結果が零でない |
0110 | MZ | 結果が負または零 |
0111 | P | 結果が正 |
1000 | EZ | Eレジスタが零 |
1001 | ENZ | Eレジスタが零でない |
1010 | OZ | Vが零 |
1011 | ONZ | Vが零でない |
1100 | LMZ | 結果が等しいまたは小 |
1101 | LP | 結果が大 |
1110 | LPZ | 結果が大または等しい |
1111 | LM | 結果が小 |
これらのフィールドは、これ以降の命令詳細のオペコード欄に現れた場合も同じ意味を持ちます。
2語目は2 word命令の第2語目の意味を示します。AD16はセグメント内アドレスを意味し、IM16は16
bit定数を意味します。
EVはEフラグとオーバーフローを意味するVフラグの変化を意味します。何も記入されていなければ変化なし、0か1が書かれていれば命令実行時に強制的にその値にされる、*なら命令の実行結果に応じて変化する、-なら不定であることを意味します。
LD, STD命令は16 bit直接番地指定でセグメント内の任意のアドレスのメモリとのデータ転送を行います。
LR, STR命令は任意のセグメントベースレジスタを用いて全アドレス空間のメモリとデータ転送を行うほか、間接レジスタのプリデクリメント、ポストインクリメント機能もあって、連続したデータを操作しやすくなっています。セグメントをまたいだブロック転送にも便利そうですが、単純なブロック転送なら専用の特殊命令としてBLK命令があります。
MV命令はレジスタ間転送命令ですが、レジスタの内容を判断するための純粋なスキップ判定命令として使用することもあります。その場合、MV
R, R, SkipCondのように、判定したいレジスタをソースとディスティネーションの両方に書きます。
MVWR命令はメモリからレジスタへのデータ転送ですから、本来はロード命令の範疇に入りそうなものです。レジスタ間接アドレッシングのため、ディスティネーションはR0に限られています。LR命令との使い分けは微妙なところですね。
MVWI命令は16 bit定数をレジスタにロードする命令で、これまでMN1610になくて少し不便なところがありました。コードのワード数は実質的には変わりませんが、ルーチンの切れ目の離れた場所に定数を定義しておいて、それを相対アドレッシングのL命令で読み込むしかできませんでしたから。
MVB命令はレジスタの下位8 bitだけの転送です。上位8 bitは変化しません。
MVBR命令は、メモリから1 Byteだけ読み込める命令ですが、やはり下位バイトに限られます。
BSWP命令は上位8 bitと下位8 bitを入れ換えながらレジスタ間データ転送を行います。ソースとディスティネーションに同じレジスタを指定すれば、単にレジスタの上下バイトを入れ換える命令としても利用できます。
BSWR命令はメモリからレジスタにデータを読み込みながら上下バイトを入れ換えます。
DSWP命令はレジスタ間のデータ転送時にビット4 - 7とビット8 - 11を入れ換えます。これとBSWP命令を併用すれば、任意のデジットをレジスタの下位4
bitに配置することができるわけで、BCDデータ処理などに応用できるでしょう。
DSWR命令はメモリからレジスタにデータを読み込みながらデジット入れ換えを行います。
PUSH命令とPOP命令はスタックとレジスタ間のデータのやりとりを行います。MN1613のスタックポインタは常に空のメモリを指しているので、PUSHした後にデクリメント、インクリメントした後にPOPという関係になります。LR,
STR命令のプリデクリメント、ポストインクリメントと逆になっています。
PSHM命令とPOPM命令はR0 - R4をまとめてスタックにPUSH, POPします。PUSHはR0が最初に行われ、POPはR4が最初に行われます。割り込み時のコンテキスト切り替えなどに便利そうです。
MVI命令は8 bit定数値をレジスタの下位8 bitに読み込みます。上位8 bitは変化しません。
データ転送系の命令ではEフラグもVフラグも変化しません。
次に整数演算命令です。
命令 オペコード
2語目 EV 動作
A 01011 ddd kkkk 1sss
** Rd <- (Rd) + (Rs), skip
AWR 01011 111 kkkk 10ii
** R0 <- (R0) + ((Ri)), skip
AWI 01011 ddd kkkk 1111 IM16 ** Rd
<- (Rd) + IM16, skip
AI 01001 rrr kkkk DDDD
R <- (R) + IM4, skip
S 01011 ddd kkkk 0sss
** Rd <- (Rd) - (Rs), skip
SWR 01011 111 kkkk 00ii
** R0 <- (R0) - ((Ri)), skip
SWI 01011 ddd kkkk 0111 IM16 ** Rd
<- (Rd) - IM16
SI 01000 rrr kkkk DDDD
R <- (R) - IM4, skip
C 01010 ddd kkkk 1sss
(Rd) - (Rs), skip
CWR 01010 111 kkkk 10ii
(R0) - ((Ri)), skip
CWI 01010 ddd kkkk 1111 IM16
(Rd) - IM16, skip
CB 01010 ddd kkkk 0sss
(Rd)_L - (Rs)_L
CBR 01010 111 kkkk 00ii
(R0)_L - ((Ri))_L
CBI 01010 ddd kkkk 0111 IM16
(Rd)_L - IM16_L
NEG 00011 111 kkkk cddd
* Rd <- -(Rd) - (E), skip
AD 01001 111 kkkk c1ii
** DR0 <- (DR0) + ((Ri), (Ri)+1) + (E), skip
SD 01000 111 kkkk c1ii
** DR0 <- (DR0) - ((Ri), (Ri)+1) - (E), skip
M 01111 111 kkkk 11ii
00 DR0 <- (R0)*((Ri)), skip
D 01110 111 kkkk 11ii
0* R0 <- (DR0)/((Ri)), R1 <- (DR0)%((Ri)), skip
DAA 01011 111 kkkk c1ii
* R0 <- (R0)_BCD + ((Ri))_BCD + (E), skip
DAS 01010 111 kkkk c1ii
* R0 <- (R0)_BCD - ((Ri))_BCD - (E), skip
LAD 01101 ddd kkkk 0sss
Rd <- LAD((Rd), (Rs)), skip
LADR 01101 111 kkkk 00ii
R0 <- LAD((Rd), ((Ri))), skip
LADI 01101 ddd kkkk 0111 IM16
Rd <- LAD((Rd), IM16), skip
上の表で、DDDDは0から15までを表す定数値です。
また、NEG, AD, SD, DAA, DAS命令の中のcフィールドの意味は、次のようになっています。
c | 意味 |
0 | 演算にキャリー(E)を含める |
1 | 演算にキャリー(E)を含めない |
A, AWR, AWI, AI命令は2進整数の加算命令です。MN1610ではレジスタ間加算のA命令と0から15までの定数値をレジスタに加算するAI命令しかありませんでしたが、レジスタ間接アドレッシングとイミディエートアドレッシングの命令が追加され、特にイミディエート命令では任意の16
bit定数の加算が可能になってコードを書きやすくなりました。AI命令は一般のプロセッサのレジスタインクリメント命令の機能強化版で、そのためかフラグには影響を与えません。
S, SWR,SWI, SI命令は2進整数の減算命令です。Eフラグは桁借りにしたがってセットされます。
これらの加減算命令には、キャリーを演算に含める機能はありません。
C, CWR, CWI命令は比較命令で、減算を行って(その結果は捨てるけれども)スキップ条件判定を行います。
CB, CBR, CBI命令はレジスタ下位8 bitに関する比較命令で、実際はふたつの数値の下位8
bitを取り出して上位8 bitは0に置き換えた数値に対しての比較となります。符号拡張は行わず、実質的に0から255までの正数値としての比較です。
NEG命令は2の補数を求める命令です。キャリー指定があれば、キャリー込み、つまりEが1の時には本来の2の補数より1少ない数が求められます。この命令は単項演算命令となっていて、元データの入っていたレジスタが書き換えられます。
AD命令とSD命令は2 word整数の加減算命令です。R0がMSB側、R1がLSB側となり、メモリ上の2
wordとの加減算が行われ、フラグも通常の加減算と同じようにセットされます。また、スキップ条件判定も結果の2
wordを正しく判定します。キャリー指定も可能なので、必要に応じて多倍長の加減算を実行可能です。逆に1
word長のA, S命令にはキャリー込みはできません。MN1610ではスキップ条件指定とAI,
SI命令などを組み合わせて桁上がりの処理を行わなくてはなりませんでした。
M命令は無符号16 bit数値の乗算を行います。R0の内容とRiで指されたメモリの内容の積をとり、R0とR1に格納します。クロック周波数13.3
MHzのときに8.4 usかかります。112クロック分ですね。一般のレジスタ間整数演算は最短0.3
us、4クロックかかるということを考えると、メモリ上のデータアクセスのために4クロックは必要ということを考えても長い実行時間です。
D命令は無符号32 bitデータを無符号16 bitデータで割る命令です。R0, R1に納められた32
bitの数値とRiで指されたメモリの内容との除算を行い、商をR0、剰余をR1に格納します。除数が0ないし商が16
bit数値の範囲を越えた場合にVフラグがセットされます。Vフラグがセットされたときの演算結果は保証されません。この除算命令はクロック周波数13.3
MHzのときに17.4 usかかるということで、232クロック消費されます。
DAA, DAS命令はBCDデータに対する加減算命令です。キャリー指定も可能で、多倍長演算も簡単に記述できます。MN1613ではLAD命令とA,
S命令を組み合わせて少々複雑なコードを書かなくてはならなかったのが、容易にコーディングできるようになりました。
LAD, LADR, LADI命令はMN1610のLAD命令にアドレッシングのバリエーションを増やしたもので、やはりBCD加減算のための補正命令です。LAD命令では補正のためのテストデータを前もって空いたレジスタにロードしなくてはならなかったのが、LADI命令では不要となります。ただ、DAA,
DAS命令が使えれば、互換性のためのLAD命令を除いて、使用する場面はかなり少なくなりそうです。
単精度相当で基本的なものしかありませんが、次の浮動小数点数演算命令が新設されています。
命令 オペコード
2語目 EV 動作
FA 01101 111 kkkk 11ii
0* DR0 <- (DR0) + ((Ri), (Ri)+1), skip
FS 01101 111 kkkk 01ii
0* DR0 <- (DR0) - ((Ri), (Ri)+1), skip
FM 01100 111 kkkk 11ii
0* DR0 <- (DR0) * ((Ri), (Ri)+1), skip
FD 01100 111 kkkk 01ii
0* DR0 <- (DR0) / ((Ri), (Ri)+1), skip
FIX 00011 111 kkkk 1111
0* R0 <- Int((DR0)), skip
FLT 00011 111 kkkk 0111
0- DR0 <- Float((R0)), skip
これらの命令で使用される浮動小数点データの形式は次のとおりです。
1語目(R0) SEEE EEEE MMMM MMMM
2語目(R1) MMMM MMMM MMMM MMMM
2進数表現で命令と同じく左端がMSBとなります。Sは仮数部の符号ビットで、0が正、1が負を意味します。EEEEEEEの7
bitが指数部で、40H(16進数)の下駄履き表現が使われています。MMMMの6桁が仮数部で、合計2
word分の32 bitデータです。小数点位置はEとMの間にあります。ここまでは、比較的普通の浮動小数点形式なのですが、最近のマイクロプロセッサの表現法と異なり、指数部は16を基底としていて、仮数部は4
bit単位でひとつの桁を表します。
具体的には、指数部が40Hなら16の0乗、41Hなら16の1乗、42Hなら16の2乗、7FHなら16の63乗を、逆に3FHなら16の-1乗、3EHなら16の-2乗、00Hなら16の-64乗という意味になり、仮数部の小数点位置は4
bit単位でずらされることになります。仮数部はデータの値が0.0以外なら正規化されていなければなりませんが、16進表現ということですから1語目の第8
bitが1という条件ではなく、第8から第11 bitが0以外という形が正規化フォーマットとなります。なお数値の0.0は全32
bitが0で表現されます。
この形式で表現されるデータ範囲は、16進表現なら±0.100000H 16**-64から±0.FFFFFFH
16**63まで、10進数表示で約±5.4E-79から±7.2E75の範囲です。精度は仮数部の最上位桁が0001というビットパターンのときに実質的に仮数部が21
bitしか使用されませんから、21 * log 2 = 6.3桁の精度を持ちます。
指数部の基底に2を用いた形式より、有効数字は減りますが、最大値と最小値の幅はこちらのほうが広く取れます。どちらかというとマイクロプロセッサでは珍しい形式ですが、大型コンピュータで使われることのあった形式です。
MN1613では、このような浮動小数点データの四則演算、および浮動小数点形式と整数形式の変換命令を用意しています。
四則演算では、演算結果が表現範囲を越えた場合にVフラグをセットし、その場合の結果は保証されません。当然ながら0での除算もVフラグがセットされます。アンダーフローについては強制的に結果を0にします。
FIX命令はDR0内の浮動小数点データを符号付き16 bit整数値に変換してR0に入れます。16
bit整数で表現できない数値だった場合にはVフラグがセットされ、結果は保証されません。
FLT命令はFIX命令の逆で、R0に納められた符号付き16 bit整数値を浮動小数点データに変換してDR0に格納します。こちらは必ず正常に変換できるはずで、Vフラグは無関係のはずですが、実際には不定となっています。
FIX命令もFLT命令も任意の数値を相互変換するには機能不足ですが、それなりに四則演算命令などと組み合わせれば数値の文字列表現から浮動小数点データへの変換やその逆も行えます。また、12
bit A/Dコンバータから入力を読み込んで浮動小数点表示に変換し、それなりに複雑な計算を行ってから、12
bit D/Aコンバータに出力して制御を行うような場合なら、これらのFIX, FLT命令をそのまま利用することができます。
さて、演算速度ですが、FA命令で15.6 - 22.8 us、FS命令で16.2 - 24.0 us、FM命令で52.2
- 58.2 us、FD命令で73.5 - 88.5 usとなっています。FD命令の最悪時で1180クロックですね。確かに整数演算命令を組み合わせたコードよりは1桁くらい高速になっていますが、別格といってよいほど長い命令実行時間です。これらの浮動小数点演算命令実行中の割り込み要求は命令終了まで待たされるはずですから、リアルタイム応用に関する割り込み応答時間はかなり悪いプロセッサとなってしまいそうです。
ただ、当時、コプロセッサとか拡張用マイクロプログラムROMを外付けせずに浮動小数点演算命令をシングルチップで実装していた例はほとんどありません。実行速度も、さすがに8086
+ 8087よりは遅いですが、Am9511よりは命令単体でもそれなりに高速ですし、データの入出力の手間まで考えればかなり有利となります。計測データのリニアライズ処理とか高速フーリエ変換の計算、あるいは測定データから何らかの複雑な計算を行って制御量を求めるとか、特にその途中の演算結果が固定小数点処理では桁落ちの危険が大きいばあいには、便利なマイクロプロセッサだと考えられます。
論理演算およびその他の演算命令については、MN1610の命令にアドレッシングのバリエーションが増やされただけです。
命令 オペコード
2語目 EV 動作
AND 01101 ddd kkkk 1sss
Rd <- (Rd) & (Rs), skip
ANDR 01101 111 kkkk 10ii
R0 <- (R0) & ((Ri)), skip
ANDI 01101 ddd kkkk 1111 IM16
Rd <- (Rd) & IM16, skip
OR 01100 ddd kkkk 1sss
Rd <- (Rd) | (Rs), skip
ORR 01100 111 kkkk 10ii
R0 <- (R0) | ((Ri)), skip
ORI 01100 ddd kkkk 1111 IM16
Rd <- (Rd) | IM16, skip
EOR 01100 ddd kkkk 0sss
Rd <- (Rd) ^ (Rs), skip
EORR 01100 111 kkkk 00ii
R0 <- (R0) ^ ((Ri)), skip
EORI 01100 ddd kkkk 0111 IM16
Rd <- (Rd) ^ IM16, skip
IMS 11MMM 110 dddd dddd
EA <- (EA) + 1, if result = 0, skip inst.
DMS 10MMM 110 dddd dddd
EA <- (EA) - 1, if result = 0, skip inst.
AND命令からEORI命令まではビットごとの論理積、論理和、排他的論理和を求める命令です。
IMS命令は、メモリ内のデータをインクリメントして、その結果が0ならスキップを行う命令です。またDMS命令は、インクリメントでなくてデクリメントを行い、その結果が0ならスキップを行う命令です。ループ制御に使用します。レジスタやフラグの内容に影響を与えないので、便利な命令です。
分岐命令にはこのようなものが用意されています。
命令 オペコード
2語目 EV 動作
B 11MMM 111 dddd dddd
IC <- EA
BD 00100 110 0000 0111 AD16
IC <- EA
BL 00100 111 0000 1111 AD16
CSBR <- (EA), IC <- (EA+1)
BR 00100 111 0000 01ii
CSBR <- ((Ri)), IC <- ((Ri)+1)
BAL 10MMM 111 dddd dddd
(SP--) <- (IC), IC <- EA
BALD 00100 110 0001 0111 AD16
(SP--) <- (IC), IC <- EA
BALL 00100 111 0001 1111 AD16
(SP--) <- (IC) (CSBR), CSBR <- (EA), IC <- (EA+1)
BALR 00100 111 0001 01ii
(SP--) <- (IC) (CSBR), CSBR <- ((Ri)), IC <- ((Ri)+1)
RET 00100 000 0000 0011
IC <- ((++SP))
RETL 00111 111 0000 0111
CSBR IC <- ((++SP))
LPSW 00100 000 0000 01LL
STR <- (L*2), IC <- (L*2+1), CSBR <- (OSR(L))
B, BD, BL, BR命令は無条件分岐です。というか、条件分岐命令はMN1613には存在しません。条件分岐を行うには、演算命令のスキップ機能で無条件分岐命令をスキップするという方法を用います。なお、MN1613のスキップ機能は、1語命令だけでなく2語命令も正しくスキップできるようになっています。BL命令とBR命令はメモリ上に確保された拡張アドレスデータをCSBRとICに読み込み、セグメント間分岐を可能にしています。
BAL, BALD, BALL, BALR命令はサブルーチン呼び出し命令で、スタックに戻りアドレスを保存してから分岐します。特にBALL,
BALR命令は拡張アドレスデータを用いてセグメントを越えたサブルーチンを呼び出すことができますが、その際はスタックにICだけでなくCSBRの内容も保存して、戻ってこれるようにしています。
RET命令はセグメント内サブルーチン呼び出しのBAL, BALD命令用のサブルーチンリターン命令です。
RETL命令はセグメント間サブルーチン呼び出しのBALL, BALR命令用の、CSBRとICの内容を復元するリターン命令です。
LPSW命令は割り込みサービスルーチンからのリターン命令で、保存されているPSW情報の場所が割り込みレベルごとに異なるため、割り込みレベルLLを指定します。LLを表にまとめると次のようになります。
LL | 割り込みレベル | STRアドレス | ICアドレス |
00 | レベル0 | 0000H | 0001H |
01 | レベル1 | 0002H | 0003H |
10 | レベル2 | 0004H | 0005H |
11 | 割り込みと無関係 | 0006H | 0007H |
この表で、STRアドレスのメモリから割り込み以前のSTRの内容を、ICアドレスのメモリから割り込み以前のICの内容を、復元します。MN1613の割り込みは3レベルですが、LPSW命令では4番目のレベルに相当する値をLLに指定しても未定義命令としては扱われず、それなりに動作し、一種の間接分岐命令のように利用できます。
ビット命令とシフト命令については4種類が新設されています。
命令 オペコード
2語目 EV 動作
TBIT 00101 rrr kkkk DDDD
(R) & Bit(D), skip
SBIT 00111 rrr kkkk DDDD
R <- (R) | Bit(D), skip
RBIT 00110 rrr kkkk DDDD
R <- (R) & ~Bit(D), skip
TSET 00010 111 kkkk 1sss AD16
(EA) & (Rs), skip, EA <- (EA) | (Rs)
TRST 00010 111 kkkk 0sss AD16
(EA) & (Rs), skip, EA <- (EA) & ~(Rs)
SRBT 00111 111 0111 0sss
R0 <- Fisrt bit pos.(Rs), reset the bit
DEBP 00111 111 1111 0ddd
Set bit pos.(R0) of Rd
SR 00100 rrr kkkk 10EE
* Shift Right with Modified E, skip
SL 00100 rrr kkkk 11EE
* Shift Left with Modified E, skip
SR, SL命令のEEフィールドはEレジスタ操作を意味するフィールドで、次の表のような操作が行われます。
EE | 記号 | 操作 |
00 | -- | 変化なし |
01 | RE | E <- 0, リセット |
10 | SE | E <- 1, セット |
11 | CE | E <- ~(E), 反転 |
TBIT, SBIT, RBIT命令はMN1610と同一動作で、DDDDで指定したビット番号のビットをそれぞれ、テスト、セット、リセットします。SBIT命令やRBIT命令でも、実行結果に応じてスキップを行います。ビット番号はMSBが0でLSBが15という規則で割り振られています。
TSET, TRST命令はMN1613で新設された命令で、マルチプロセッサないしマルチタスク環境下での排他制御に利用するための命令です。要はビットのテストと変更を不可分なバスサイクルで実行する命令です。16
bit直接番地指定でアドレッシングされたメモリからデータを読み込み、指定されたレジスタとの論理積を取り、スキップ条件をセットします。さらに、TSET命令の場合はレジスタの値と読み出した値の論理和を取り、レジスタのビットが1になっている場所をセットした上で、メモリに書き戻します。TRST命令の場合にはレジスタのビットが1になっている場所をリセットして、メモリに書き戻します。メモリの読み出しと書き込みは不可分なサイクルとなっていて、途中に割り込みが入る場合はもちろん、マルチプロセッサの場合でも、読み出しと書き込みの間に別のメモリアクセスが入らないようになっています。このしくみによって、メモリの初期値を0、レジスタに1を入れてスキップ条件にZを与えたTSET命令を使うなどすれば、クリティカルセクションの排他制御に使われるセマフォの実装などが可能になります。ただ、この命令の面倒な点は16
bit直接番地指定というところにあって、ユーザープロセスが直接TSET命令でセマフォを実装するわけにはいきません。異なるセグメントで実行されているプロセス同士でセマフォ用のメモリを共有できませんから。もちろん、すべてのセマフォ管理はオペレーティングシステムのシステムコールに任せるようにして、OS側でセマフォ用のメモリ割り当てまで管理すればよいだけのことで、セマフォを使うシステムなら一般的な設計に準じるだけのことだけです。
SRBT命令もMN1613で新設された命令で、指定されたレジスタの内容をMSBから調べていき、最初に1となっているビットを見つけたら、そのビット番号をR0に書きこむと共に、そのビットを0にリセットする命令です。すべて0の場合には10HがR0に入ります。ビットマップディスプレイとかキースキャンの類で使われるかもしれません。
DEBP命令もMN1613で新設されたもので、R0の下位4 bitをビット番号と解釈し、指定されたレジスタの、そのビット番号で指示されたビットを1にセットします。R0の上位12
bitは無視されます。やはりビットマップディスプレイとかキースキャンのような状況で利用可能な命令です。
SR命令とSL命令は指定されたレジスタとEレジスタを連結したうえでシフト(というよりローテート)を行う命令です。シフトに先立って、EEフィールドで指示されたEレジスタ操作が行われます。実質的にEレジスタ操作を与えなければローテート命令、REを指定すれば論理シフト命令となります。
最後に特殊命令を紹介します。
命令 オペコード
2語目 EV 動作
BLK 00111 111 0001 0111
While (R0) !=0 {(R1++) <- ((R2++)), R0--}
RD 00011 rrr dddd dddd
R <- (IM8_IO)
RDR 00100 rrr 0001 01ii
R <- ((Ri)_IO)
WT 00010 sss dddd dddd
IM8_IO <- (Rs)
WTR 00100 rrr 0001 00ii
(Ri)_IO <- (R)
LB 00001 111 0bbb 0111 AD16
BRd <- (EA)
LS 00001 111 0ppp 1111 AD16
SRd <- (EA)
STB 00001 111 1bbb 0111 AD16
EA <- (BRs)
STS 00001 111 1ppp 1111 AD16
EA <- (SRs)
CPYB 00001 111 1bbb 0ddd
Rd <- (BRs)
CPYS 00001 111 1ppp 1ddd
Rd <- (SRs)
CPYH 00111 111 1hhh 0ddd
Rd <- (HRs)
SETB 00001 111 0bbb 0sss
BRd <- (Rs)
SETS 00001 111 0ppp 1sss
SRd <- (Rs)
SETH 00111 111 0hhh 0sss
HRd <- (Rs)
H 00100 000 0000 0000
CPU Stop
ここでbbbフィールドはセグメントベースレジスタを指定するものです。
bbb | レジスタ(W) | レジスタ(R) |
000 | --- | CSBR |
001 | SSBR | SSBR |
010 | TSR0 | TSR0 |
011 | TSR1 | TSR1 |
100 | OSR0 | OSR0 |
101 | OSR1 | OSR1 |
110 | OSR2 | OSR2 |
111 | OSR3 | OSR3 |
pppフィールドは特殊レジスタを意味していて、次のようになっています。
ppp | レジスタ |
000 | SBRB |
001 | ICB |
010 | NPP |
hhhフィールドはハードウエア制御レジスタを指定します。
hhh | レジスタ(W) | レジスタ(R) |
000 | TCR | TCR |
001 | TIR | TIR |
010 | TSR | TSR |
011 | SCR | SCR |
100 | SSR | SSR |
101 | SOR | SIR |
110 | IISR | IISR |
BLK命令はメモリのブロック転送を行う命令で、R1とTSR0で指定されるアドレスからR2とTSR1で指定されるアドレスへ、R0で指定される語数のデータを転送します。独立したセグメントレジスタを使えるので、任意の物理アドレス間の転送が可能です。理屈の上では転送語数に応じてms単位の実行時間が必要な場合もありますが、この命令では1回の転送サイクルの区切りごとに割り込みを受け付けるので、割り込み応答時間には悪影響を与えません。
RD命令とRDR命令は入力ポートからの読み込みを行います。MN1613はメモリとは独立したI/O空間を備えていて、16
bitでアドレッシングされます。RD命令はMN1610と互換性のある命令で、MN1610のI/O空間は256語しかなかったので8
bitで全I/O空間を指定していました。MN1613ではI/Oアドレスの上位8 bitが0で補われて、いわばI/O空間のゼロページにだけ参照します。RDR命令はレジスタ間接アドレッシングで全I/O空間を参照可能としています。
WT命令とWTR命令は出力ポートへ書き込みを行う以外はRD, RDR命令と同一です。
LB命令はメモリからセグメントベースレジスタへのデータ転送を行います。ただしCSBRについて直接書き換えることは禁止されていて、無理にbbbフィールドに000を指定すると未定義命令扱いされます。一般のセグメントベースレジスタのほか、割り込み時にCSBRを退避させるOSRxレジスタも扱うことができます。
STB命令はLB命令の逆を行うもので、ベースレジスタ類をメモリに退避させることができます。OSRxの退避と復帰ができるので、適切に使用すればOPSW領域の退避と復帰を合わせて多重割り込みも可能となります。後述のコンソール処理プログラムからはCSBRの退避を行おうとしても、正しい値が得られないことがあります。
LS, STS命令は特殊レジスタに対してLB, STB命令と同じことを行います。表にはpppフィールドの意味としてSBRB,
ICBも含まれていますが、これらのレジスタ操作に関しては後述のコンソール処理プログラムでのみ可能で、通常の実行状態では未定義命令扱いされます。
CPYB, CPYS, SETB, SETS命令は、それぞれセグメントベースレジスタないし特殊レジスタと汎用レジスタ間の転送命令です。注意点も同じです。
CPYH, SETH命令はハードウエア制御レジスタ(IISRを含む)とレジスタ間のデータ転送を行うための命令です。内蔵のタイマや直列入出力機能に関するレジスタはI/O空間には割り当てられずに、このような特殊命令でのみアクセス可能となっています。ちなみにhhhフィールドに111を指定すると、それぞれDEBP,
SRBT命令のビットパターンとなってしまいます。
H命令はプロセッサを停止状態に遷移させる命令です。
ちなみに、00000 000 0000 0000というビットパターンは未定義命令、11111
111 1111 1111というビットパターンはB命令として解釈されます。NOPが必要なら、MV
R0, R0などの命令を代用します。
未定義命令を実行すると、レベル0内部割り込みが発生し、IISRのビット15が1にセットされます。
パナファコムはMN1613のあと、浮動小数点演算命令を強化した?MN1617を開発しています。
Return to Collection