公開日:2021/02/20
15th Season
#15-3 マイコンを作るよ(付録)
このページは、本HPで作成したオリジナル16ビットCPUコアMoscoviumの命令セットマニュアルです。
詳細については、以下リンクから本文を参照してください。
本文へ戻る。
Moscovium Instruction Set Manual
Moscovium CPUコア概要
Moscoviumは、シンプルな16ビットCPUコアです。ハーバードアーキテクチャを採用しており、命令コードを16ビットフェッチバスから読み込んで実行します。同じく16ビットのメモリバスを通して、CPU外部のRAMやI/Oユニット(メモリマップドI/O)などのリソースにアクセスすることが出来ます。
フェッチバス、メモリバス共、16ビットアドレスバスを持っており、従ってメモリ空間は最大64Kバイトです。
命令コードは16ビット固定長で、フェッチバス上の16ビットワード境界に乗っていることを前提とします。言い換えると、常に偶数バイトアドレスから16ビット命令コードが配置されています。
プログラムカウンタpcはリセット信号で0x0000に初期化されるので、Moscoviumリセット解除後、常に0x0000番地の命令から実行を開始します。
- 凡例:
- Rd: 転送先レジスタ。汎用レジスタ(r0〜r7)のいずれか。
- Rs: 転送元レジスタ。汎用レジスタ(r0〜r7)のいずれか。
- Rn: 汎用レジスタ(r0〜r7)のいずれか。
- Rd’: 命令実行後のRdレジスタ、またはその値。
- Rc: 制御レジスタ(sr,pc,sp,iv,tr)のいずれか。
- dsp11: 分岐命令の変位量。11ビット符号付整数。
- imm8: 即値。8ビット符号無整数。
- 16ビットレジスタとの演算では、imm8を16ビットにゼロ拡張して使用する。
- [Rn]: 汎用レジスタRnの間接アドレッシング。
- 汎用レジスタRnの値をアドレスと見て、そのアドレスにあるデータにアクセスすることを表す。
- [--Sp]: スタックポインタのプリデクリメント間接アドレッシング。
- スタックポインタspを先にデクリメント(−2)してから、Spが示すアドレスにデータを書き込む。
- [Sp++]: スタックポインタのポストインクリメント間接アドレッシング。
- スタックポインタspが示すアドレスに格納されたデータを読み出した後で、Spをインクリメント(+2)する。
- [Sp+Rn]/[Sp,Rn]: スタックポインタからの相対間接アドレッシング。
- スタックポインタspに汎用レジスタRnの値を加算したアドレスにアクセスする。
- [Tr:Rn]/[Tr,Rn]: 32ビット拡張アドレスを示すレジスタペアの間接アドレッシング。
- 一時レジスタtrを上位16ビット、汎用レジスタRnを下位16ビットアドレスとする32ビット拡張アドレス指定となる。
- Rn[k]: レジスタRnのビットkを表す。
- MSB(Most Significant Bit)がk=15、LSB(Least Significant Bit)がk=0。
- k=16として、演算結果のキャリ出力を表現する場合がある。
- k=−1として、右シフト演算結果のシフトアウト出力を表現する場合がある。
- Sr[C]などとして、状態レジスタsrのCフラグ(ビット)を表す場合がある。
- Rn[a:b]: レジスタRnのビット範囲(第aビット〜第bビット)を表す。
- {…,…}: { }内に記載したデータを上位ビットから順に結合したデータを表す。
- 動作: 「動作:」記述中の演算子(!,×,÷)は、各々、ビット毎論理NOT、算術乗算、除算演算子を表す。その他の演算子はC言語などと同じ。
- 状態: 「状態:」記述中の演算子(×,+,^,!)は、各々、ビット毎論理AND、OR、EOR、NOT演算子を表す。
Moscoviumシリーズ
Moscoviumシリーズは、オリジナル16ビットCPUコアMoscoviumを起点とする、スケーラブルなCPUコアシリーズです。
16ビットMoscoviumから、上位側にオリジナル32ビットCPUコアNihonium、下位側にオリジナル8ビットCPUコアTennessineがスケーラブルに展開されています。Moscovium,Nihonium,Tennessineの各CPUコアをまとめてMoscoviumシリーズと呼びます。
各種マニュアルへのリンク:
Moscoviumシリーズは、基本的に16ビット固定長の共通した命令コードを持ち、ハンドリングするデータのビット幅が、8ビット以下である場合、全く同じオブジェクトコードレベルのプログラムを、全てのCPUコアで共通して動作させることができます。
※ただし、ほとんどのプログラムでは、最低でも16ビット長のデータハンドリングが必要となるため、8ビットCPUであるTennessineコアだけは、別プログラムが必要となることが多いです。
以下表にMoscoviumシリーズの特徴を示します。
機能\CPUコア |
Moscovium |
Nihonium |
Tennessine |
演算器ビット幅 |
16ビット |
32ビット |
8ビット |
命令コード |
16ビット固定長 |
16ビット固定長
一部多ワード長命令
|
16ビット固定長 |
命令数 |
100個 |
122個 |
72個 |
汎用レジスタ数 |
8個×4バンク |
8個×2バンク |
8個×2(表/裏) |
メモリバス幅 |
16ビット |
32ビット |
16ビット |
メモリバス空間 |
32ビット(4Gバイト) |
32ビット(4Gバイト) |
16ビット(64Kバイト) |
フェッチバス幅 |
16ビット |
16ビット |
16ビット |
フェッチバス空間 |
16ビット(64Kバイト) |
16ビット(64Kバイト) |
16ビット(64Kバイト) |
論理規模 |
約3,000LUT |
約6,000LUT |
約1,500LUT |
乗算命令 |
16ビットコプロセッサ
(1サイクル)
|
32ビット内蔵
(2サイクル)
|
8ビット内蔵
(1サイクル)
|
除算命令 |
32ビットコプロセッサ
(14サイクル)
|
32ビット内蔵
(10サイクル)
|
− |
浮動小数 |
16ビット半精度
コプロセッサ
|
16ビット半精度
32ビット単精度
コプロセッサ
|
− |
8〜32ビットまで、スケーラブルに展開されているので、マクロアセンブラレベルで同じプログラムを使用して処理が可能です。データビット幅等による処理能力の違いや、FPGAボードの集積論理規模(LUT数)等に従った柔軟なCPU選択を提供します。
CPUコア名の由来
CPUコア名のMoscovium/Nihonium/Tennessineは、原子の名前に由来しています。
- Moscovium
- 原子番号115
- 原子記号Mc
- モスコビウム(Mc)は放射性が強く、半減期はミリ秒オーダ。崩壊するとNihoniumになることがある。
- オリジナル16ビットCPUコアの名前に選定した理由は、「MCU(Micro Controller Unit)」から、Mcを取って、元素記号のMc → モスコビウム(元素番号115)と連想したため。
- Nihonium
- 原子番号113
- 原子記号Nh
- 日本の研究者が合成したことで命名権を獲得、「日本」にちなんで命名された(2016年)。
- ニュースにもなったので、ご存知の方も多いと思う。
- 新たな元素を発見して命名したのは、アジアでは「初」だったとか。
- Tennessine
- 原子番号117
- 原子記号Ts
- アメリカとロシアの合同チームが発見して、アメリカ合衆国テネシー州にちなんで命名され、正式承認(2016年)された。
いずれの原子も質量数100を超える重たい原子であり、その様な原子は不安定で、安定して自然界に存在できません。皆、数ミリ秒オーダの半減期で崩壊して、より軽い原子へ変化して行く放射性物質です。ミリ秒オーダでしか存在できない原子のため、存在は予想できても確認することができず、古い周期表などでは名前が明記されていない物も見かけます。
とある同位体は、
- ……
- Tennessine(原子番号117)が崩壊して、Moscovium(原子番号115)に変化。
- Moscovium(原子番号115)が崩壊して、Nihonium(原子番号113)に変化。
- ……
することが知られています。これをビット幅の小さい8ビットCPUから順に割り当てました。
プログラマモデル
Moscoviumのプログラマモデルは以下図の通りです。
汎用レジスタ8本(r0〜r7)と、状態レジスタsr、プログラムカウンタpc、スタックポインタsp、割り込みベクタiv、一時レジスタtrの構成です。すべてのレジスタはリセット解除後、0x0000に初期化されています。汎用レジスタ8本には4組の汎用レジスタバンクが有って、Srレジスタの{BK1,BK0}フィールドにて、切り替えて使用することが可能です。
制御レジスタ
Srは状態レジスタです。演算結果を示すフラグビット(N,C,V,Z)等、CPUの状態を示すビットを備えています。
状態ビット:
- ID1,ID0:CPU ID
- 2ビットのIDフィールド={ID1,ID0}からは、以下のCPU IDを読み出すことが出来ます。
- ID=0: シングルコアCPUだった場合。
- ID=1: SMPデュアルコアCPU版で、メインCPU(CPU1)だった場合。
- ID=2: SMPデュアルコアCPU版で、サブCPU(CPU2)だった場合。
- ID=3: AMPデュアルコアCPU版で、メインCPU(CPU1)だった場合。
- このフィールドはリードオンリなので、ldch命令やsesrh命令などを使っても書き換えることはできません。
- ML:32ビット乗算結果(初期値0)
- 16×16ビットの乗算では、積は32ビット長となります。
- 乗算命令(muls命令、mulu命令)実行時、32ビット長の演算結果を取得するか否かを選択するビットです。
- ML=0: 16×16=32ビット演算を実施して、積32ビットの下位16ビットだけが結果として戻ります。
- ML=1: 16×16=32ビット演算を実施して、積32ビットを2個の汎用レジスタに分割してセットします。
- ※MLビットに関しては、初期値であるML=0で使う事を強く推奨します。
- MLビットは、mulsr命令、mulur命令を追加したことで、設定を変更する必要がなくなったため。
- 将来廃止する可能性を排除しないので、現行プログラムについても、修正することを推奨する。
- DR:剰余演算(初期値0)
- 除算命令(divlq命令、divlr命令、divs命令、divu命令)の実行時、剰余を取得するか否かを選択するビットです。
- DR=0: 除算の演算結果として商だけを汎用レジスタにセットします。
- DR=1: 除算の演算結果として商と剰余を別々な汎用レジスタにセットします。
- ※DRビットに関しては、初期値であるDR=0で使う事を強く推奨します。
- SD:スーパスケイラモード選択(初期値0)
- スーパスケイラ版CPUコアの場合に、SD=1を設定すると、スーパスケイラが無効化できるビットです。
- リセット解除後のデフォルトはSD=0で、スーパスケイラが有効になっています。
- 通常版CPUコアでは、本ビットは常に0となります。
- N:ネガティブフラグ
- C:キャリフラグ
- 演算の結果、キャリ(またはボロウ)が発生した場合に1となります。
- V:オーバフロウフラグ
- 演算の結果、符号付整数のオーバフロウが発生した場合に1となります。
- Z:ゼロフラグ
- IE1,IE0:割り込み許可レベル(初期値0)
- CPUに割り込み要求がアサートされ、IEフィールド={IE1,IE0}値より高い(数値としては小さい)割り込みレベルだった場合、CPUは割り込み処理を開始します。
- IE=0では、割り込み禁止なので、割り込み要求がアサートされてもCPUは無視して通常処理を続けます。
- IE=3では、全ての割り込み要求を受け付けて、割り込み処理を開始します。
- CPUが割り込みを受け付けると、受け付けた割り込みレベルがIEフィールドに設定されます。
- これによって、受け付けた割り込みレベルと、同じか、より低い優先度の割り込み受付は禁止され、より高い優先度の割り込みは多重に受け付けられます。
- 割り込みサービスルーチンからrti命令で復帰する時、状態レジスタsrが回復されて、元の割り込み許可レベルに戻ります。
- BK1,BK0:汎用レジスタバンク番号(初期値0)
- 汎用レジスタのバンク番号BK={BK1,BK0}を指定します。
Pcはプログラムカウンタです。Pcの指し示すアドレスからプログラムコードをフェッチして実行します。フェッチすると、自動的にインクリメント(+2加算)されます。
Pcの指し示すアドレスは、フェッチすべき命令のバイトアドレスです。命令コードは16ビット固定長で、16ビットワード境界に乗っているので、Pcは常に偶数となります。Pcが16ビット長なので、プログラムメモリ空間は最大64Kバイトです。
Pcはリセット解除後、0x0000に初期化されているので、Moscoviumは0x0000番地から命令を実行開始します。
Spはスタックポインタです。Moscoviumのスタックは、「フル下降型」で固定です。スタックの構成方法については以下の通りとなります。
- フル下降型:
- スタックポインタspの指し示すアドレスには、有効データが格納されている(フル)。
- 新たにスタックにデータを書き込む際には、予めSpを減算(下降、プリデクリメント)してから、データを書き込む。
- 読み出す場合は、その逆の処理となる。以下、省略。
- フル上昇型:
- スタックポインタspの指し示すアドレスには、有効データが格納されている(フル)。
- 新たにスタックにデータを書き込む際には、予めSpを加算(上昇、プリインクリメント)してから、データを書き込む。
- エンプティ下降型:
- スタックポインタspの指し示すアドレスには、有効データが格納されていない(エンプティ)。
- 新たにスタックにデータを書き込む際には、現在のSpアドレスにデータを書き込んでから、Spを減算(下降、ポストデクリメント)する。
- エンプティ上昇型:
- スタックポインタspの指し示すアドレスには、有効データが格納されていない(エンプティ)。
- 新たにスタックにデータを書き込む際には、現在のSpアドレスにデータを書き込んでから、Spを加算(上昇、ポストインクリメント)する。
Ivは割り込みベクタです。Moscoviumが割り込みを受け付けると、プログラムカウンタpc→状態レジスタsrの順でスタックに積んだ後、Pc=IvとしてIvが示すアドレスに分岐します。
ベクタ割り込み方式についても、ご確認ください。
Trは一時レジスタです。スタックポインタ相対間接アドレッシング命令(ldwsp命令,stwsp命令)が一時的に使用して、データを破壊します。対象の命令を使わない時は、ユーザリソースとして使用可能です。
以下の如く、汎用レジスタバンク間のデータ転送などに使用することが可能です。
ldcl sr,0x01 // バンク1を選択
movtc tr,r1
ldcl sr,0x02 // バンク2を選択
movfc r1,tr
通常、Moscoviumのアドレス空間は16ビット(64Kバイト)ですが、これを32ビット(4Gバイト)に拡張して使うことが出来ます。
32ビット拡張アドレスは、Trレジスタを上位16ビット、汎用レジスタRnを下位16ビットとするレジスタペアで指定します。
従来のldb命令,stb命令,ldw命令,stw命令では、16ビットアドレス空間へのアクセスとなり、32ビット拡張アドレス空間へアクセスする命令は、ldbx命令,stbx命令,ldwx命令,stwx命令となります。
// 32ビット拡張バス空間へのアクセス例
equ adr32,0x00801234
ldc tr,adr32>>16
ldwi r7,adr32&0xffff
ldwi r0,0xabcd
stwx [r7],r0
ldbx r1,[r7]
Tr=0だった場合、通常の16ビット空間へのアクセスと同じになります。24ビットに拡張されたメモリ空間(メモリマップ)に関してはこちらをご参照ください。
一時レジスタtrを破壊する命令や、割り込み処理中でTrを使う場合など、十分注意して使用してください。
ベクタ割り込み方式
割り込みベクタivの最下位ビットにVEビットが割り当てられています。
割り込みベクタは、ワードアドレスを指定するレジスタなので、最下位ビット=0として設定するのが普通です。
- VEビット=0と設定した場合:
- CPUが割り込みを受け付けると、プログラムカウンタpcと状態レジスタsrをスタックに退避した後で、Ivが指し示すアドレスに分岐します。
- Ivの指し示すアドレスに記述されたプログラムを割り込みサービスルーチン(ISR;Interrupt Service Routine)と呼びます。
- 全ての割り込みがIvの指し示すアドレスに分岐するのでISR内で最初に実行すべき仕事は、「どの割り込み要因で割り込みがかかったのか?」を知ることとなります。
- VEビット=1と設定した場合:
- Ivが指し示すアドレスには、ISR本体ではなく、割り込みベクタテーブルが格納されています。
- VE=1なので、Ivは奇数アドレスを指していますが、最下位ビットを無視した(0と見なした)アドレスがベクタテーブルの先頭アドレスとなります。
- 割り込みベクタテーブルとは、割り込み要因毎に実行すべきISRのアドレスを記したテーブルです。
- 割り込みベクタは1〜32の数値で、INTCからCPUに通知されます。
- CPUが割り込みを受け付けると、プログラムカウンタpcと状態レジスタsrをスタックに退避した後で、Ivが指し示すアドレス+割り込みベクタ×2のアドレスから1ワードのデータを取り出します。
- 取り出したデータをISRのアドレスと見て分岐します。
VE=1と設定した時がベクタ割り込み方式の割り込みとなります。以下に割り込みベクタテーブルの作成例を示しておきます。
// ================================
// interrupt vector table
vectab:
bra setup // 00: (reserved)
datw lab_interr // 01: ICR1
datw lab_interr // 02: ICR2
datw lab_extint0 // 03: EIR0
datw lab_interr // 04: EIR1
datw lab_interr // 05: SRAR
datw lab_interr // 06: STAR
datw lab_interr // 07: MRAR
datw lab_interr // 08: MTER
datw lab_interr // 09: (reserved)
datw lab_interr // 10: CMBR0
datw lab_interr // 11: CMAR0
datw lab_interr // 12: OVFR0
datw lab_interr // 13: (reserved)
datw lab_interr // 14: CMBR1
datw lab_interr // 15: CMAR1
datw lab_interr // 16: OVFR1
datw lab_interr // 17: (reserved)
datw lab_interr // 18: (reserved)
datw lab_interr // 19: (reserved)
datw lab_interr // 20: (reserved)
datw lab_interr // 21: (reserved)
datw lab_interr // 22: LOFR
datw lab_interr // 23: RTCR
datw lab_interr // 24: CENR
datw lab_interr // 25: SMUR1
datw lab_interr // 26: SMRR1
datw lab_interr // 27: FTAR1
datw lab_interr // 28: FRAR1
datw lab_interr // 29: SMUR2
datw lab_interr // 30: SMRR2
datw lab_interr // 31: FTAR2
datw lab_interr // 32: FRAR2
org 0x0800,align
// interrupt error routine
interr:
// something to do
rti
// EIR0 interrupt service routine
extint0:
// something to do
rti
この(↑)ベクタテーブルでは外部端子割り込みEIR0だけに、有効なISRアドレス(extint0)が設定されているので、EIR0割り込みを受け付けると正しく割り込み処理が実行されます。必要に応じて、割り込みを受け付けたいベクタに、有効なISRアドレスを設定してください。
また、ベクタ番号0番は存在しないため、Ivレジスタで指定したアドレス+0番地のデータは不問です。上のコード例では、エラー処理に飛ばすための「bra interr」を配置しています。データは不問なので、ダミーデータでもnop命令等でも問題ありません。
上に示したベクタテーブルを割り込みベクタivに設定するには、以下の様にします。
ldc iv,lab_vectab+ivec_ve
ivec_veを追加して、VEビットを立てる必要があります。ベクタテーブルアドレスを指定したにもかかわらず、VEビット=0で設定してしまった場合、Ivレジスタの示すvectabアドレスをISRの先頭アドレスと見て分岐して、そこにある「bra interr」によって、エラー処理ルーチンに分岐することになります。
ivec_veは、共通インクルードファイル(mcoc115.incl)で定義されています。「equ ivec_ve,0x0001」です。
半精度浮動小数演算ユニット(Half precision FPU)
コンパイルオプションで半精度浮動小数演算ユニット(H-FPU)を選択すると、半精度浮動小数演算を実行する命令が使用可能となります。
半精度浮動小数(IEEE 754 binary16、half-float、FP16)は、C言語で一般的に適用されているfloat型(32ビット)、double型(64ビット)に対して、16ビット長の浮動小数表現です。IEEE754では、「交換形式」として定義されていて、データ転送やストレージに使用される形式とされています。
half型のバイナリデータは以下図のような形式となっています。
符号(Sx)1ビット、指数(Ex’)5ビット、仮数(Fx’)10ビットの計16ビットです(↓)。
half型X=(−1)Sx×0x1.<Fx’>×2Ex’−15
16ビットCPUであるMoscoviumにとって、非常に扱い易いサイズの浮動小数値です。Moscoviumの汎用レジスタ(16ビット)をそのまま浮動小数レジスタに転用して、レジスタ間の演算を実行するコプロセッサがHalf precision FPU(H-FPU)であり、コンパイルオプションで有り/無しを選択できるようになっています。
half型で表現可能な数値は、−65,504〜+65,504、±INF(無限大)、±0、NaN(非数)となっていて、IEEE754に規定されている非正規化数は、全て0と見なして演算します。
- INF=0x7c00
- −INF=0xfc00
- (−)NaN=0xfe00
- MoscoviumのH-FPUでは+NaNは発生しないので、以降単にNaNと記します。
- 0=0x0000
- −0=0x8000
- HALF_MAX=65,504=0x7bff
- −HALF_MAX=−65,504=0xfbff
仮数Fxの有効ビット数が10ビットなので、10進数換算ではlog10(210)≒3.010と、有効数字3桁ほどです。
※尚、複数パタンの表現が可能なNaNや、未対応の非正規化数が入力された場合、各々NaN(0xfe00)とゼロへ縮退して処理します。
非有限値との演算
- NaNとの演算は全てNaN(0xfe00)。
- 以下、有限値A(≧0)とする。明示的にゼロ(0)との演算が記載されない場合、Aはゼロを含む。
- 加算:
- half型は符号付数なので、結果として加算となる、A+Bおよび、−(A+B)を加算とする(A≧0,B≧0)。
- INF+INF=INF
- INF+A=INF
- (−0)+(−0)=−0
- 0+0=0
- 加算は可換なので、被加数と加数を交換しても演算結果は同じ。
- 減算:
- half型は符号付数なので、結果として減算となる、A−Bおよび、−(A−B)を減算とする(A≧0,B≧0)。
- INF−INF=NaN
- INF−A=INF
- A−INF=−INF
- A−A=0
- (−A)−(−A)=0
- 乗算:
- INF×INF=INF
- INF×0=NaN
- INF×A=INF
- NaN以外の演算では、別途符号が演算される。
- 乗算は可換なので、被乗数と乗数を交換しても演算結果は同じ。
- 除算:
- INF÷INF=NaN
- INF÷0=INF
- INF÷A=INF
- 0÷INF=0
- 0÷0=NaN
- 0÷A=0
- A÷INF=0
- A÷0=INF
- NaN以外の演算では、別途符号が演算される。
- 全演算で、演算結果が有限値Aの絶対値最大値=65,504を超えた場合はINFとなる。
浮動小数値の大小比較は、hcmp命令を使います。
例)half型汎用レジスタr0とr1の大小を比較する
hcmp r0,r1 // hcmp命令によって、状態レジスタsrのフラグがセットされる
beq equal // r0=r1の時、分岐
bne not_equal // r0≠r1の時、分岐
bmi less_than // r0<r1の時、分岐
bpl greater_or_equal // r0≧r1の時、分岐
bcs equal2 // r0=r1(NaN同士、INF同士のケースも等しい(=)と見なす)の時、分岐
bvs exception_nan // r0−r1=NaNの時、分岐
hcmp命令(hcmp Rd,Rs)では、Rd−Rsの演算を実行して、演算結果に従って状態レジスタsrの演算フラグ(N,C,V,Z)をセットします。減算結果Rd−RsはレジスタRdには戻さないので、Rd,Rs共、命令実行時の値が保存されます。
Zフラグのセットに於いては、常に0=−0として扱います。従って、Rd−Rs=−0の場合、N=1、Z=1となります(そのまま「負のゼロ」。hsub+movでは、N=1、Z=0であることに留意)。
従来通り、減算hsub命令を使う方法も有効です(↓)。ただし、INFやNaN、−0等の例外を処理するのに手間がかかるため、hcmp命令の使用を推奨します。
例)half型汎用レジスタr0とr1の大小を比較する
hsub r0,r1
cmpi r0,0 // hsub命令ではSrレジスタの演算フラグが変化しないので必要
beq equal // r0=r1の時、分岐
bpl greater_or_equal //r0≧r1の時、分岐
bmi less_than // r0<r1の時、分岐
mov命令でセットされるSrレジスタのフラグは、ネガティブNフラグとゼロZフラグだけなので、有効な分岐命令はbeq命令、bne命令、bpl命令、bmi命令です。
r0,r1が無限大(INF)やNaNなど非有限値の場合や、演算結果が−0(負号付きゼロ)だった場合の大小比較には注意してください。hsub命令(上のコード例)では大小比較不能なケースがあります。
特に、負号付きゼロは「−10×0=−0」など、比較的頻繁に出現します。half型バイナリデータでは、half(−0)=0x8000であり、「cmpi r0,0」によって、状態レジスタsrのネガティブNフラグが立って、同ゼロZフラグがネゲートされるため、beq命令では分岐せず、bmi命令で分岐します。
この様な特別な値(INFやNaN等)については、以下の様にuint16値として直接比較することを推奨します。
例)half型汎用レジスタr0がINFがどうか?
ldwi r1,0x7c00 // 0x7c00はhalf型では+INFの表現
cmp r0,r1 // r0が+INFか?
beq r0_is_inf
C言語などを使ってプログラミングしていると、この辺りの例外処理はC言語が処理してくれています。float型やdouble型だと、演算結果がオーバフロウしてINFが出力されるケースも少ないでしょう。half型では、絶対値が65,504を超えただけでINFが出力されるので、このような非有限値の例外処理を実行すべきケースが増加しています。
しかも、Moscoviumプログラミングの基本はアセンブラなので、十分注意してプログラムしてください。
命令コード
Moscoviumの命令コードは16ビット固定長で、プログラムメモリ空間の16ビットワード境界に乗っています。
命令セットの形式(命令群)と命令コードの対応は以下表の様になっています。
ビット |
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
NO命令群 |
0 |
0 |
0 |
0 |
0 |
OPC_NO |
BR命令群 |
0 |
OPC_BR |
dsp11 |
RR命令群 |
0 |
1 |
1 |
1 |
0/1 |
OPC_RR |
Rd |
Rs |
R命令群 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
0/1 |
0/1 |
OPC_R |
Rn |
RI命令群 |
1 |
OPC_RI |
Rd |
imm8 |
- NO命令群: OPC_NO
- BR命令群: OPC_BR
- オペランドが「相対変位値(ディスプレースメント)」形式の分岐命令群です。
- RR命令群: OPC_RR
- オペランドが「レジスタ,レジスタ」形式の命令群です。
- R命令群: OPC_R
- RI命令群: OPC_RI
汎用レジスタを指定するRd,Rs,Rn等のフィールドには、3ビット(レジスタ番号0〜7を表現するため)が割り当てられています。即値imm8とディスプレースメント値dsp11も、命令コード内に含まれています。
OPC_BRに割り当てた4ビット(0x0〜0xfまで16個)の中で、0x0と0xe、0xfの3コードはBR命令群以外の命令に割り当たっているので、BR命令群に使える命令コード数は最大13個です。
同様に、OPC_RRに割り当てた6ビット(0x00〜0x3fまで64個)の中で、0x3c〜0x3fの4コードはR命令群に割り当たっているので、RR命令群に使えるコード数は最大60個となります。
Nihoniumに於いて、一部、16ビット/32ビット即値を取る命令では、16ビット命令コードの直後に16ビットまたは32ビット即値データが続き、2〜3ワード命令を形成します。
命令セット一覧
以下に命令セットの形式順で命令セット一覧表を示します。
No. |
Inst |
Opr1 |
Opr2 |
Type |
Memo |
O15
(1b)
|
RiBr
(4b)
|
RR
(5b)
|
R
(3b)
|
NO
(11b)
|
1 |
nop |
− |
− |
NO |
no operation |
0 |
0 |
− |
− |
0 |
2 |
pause |
− |
− |
NO |
pause until interrupt request coming |
0 |
0 |
− |
− |
1 |
3 |
rtnw |
− |
− |
NO |
return from jalw |
0 |
0 |
− |
− |
2 |
4 |
rti |
− |
− |
NO |
return from interrupt |
0 |
0 |
− |
− |
3 |
5 |
divlu |
− |
− |
NO |
divide long unsigned |
0 |
0 |
− |
− |
4 |
6 |
divls |
− |
− |
NO |
divide long signed |
0 |
0 |
− |
− |
5 |
7 |
divlq |
− |
− |
NO |
load quotient and remainder |
0 |
0 |
− |
− |
6 |
8 |
divlr |
− |
− |
NO |
restore quotient and remainder |
0 |
0 |
− |
− |
7 |
9 |
brn |
− |
− |
NO |
branch never |
0 |
0 |
− |
− |
10 |
10 |
divlqr |
− |
− |
NO |
load quotient and remainder reversal |
0 |
0 |
− |
− |
12 |
11 |
divlrr |
− |
− |
NO |
restore quotient and remainder reversal |
0 |
0 |
− |
− |
13 |
12 |
bra |
dsp11 |
(always) |
BR |
branch always |
0 |
1 |
− |
− |
− |
13 |
bne |
dsp11 |
(Z=0) |
BR |
branch if not equal |
0 |
2 |
− |
− |
− |
14 |
beq |
dsp11 |
(Z=1) |
BR |
branch if equal |
0 |
3 |
− |
− |
− |
15 |
bcc |
dsp11 |
(C=0) |
BR |
branch if carry clear |
0 |
4 |
− |
− |
− |
16 |
blo |
dsp11 |
(C=0) |
BR |
branch if lower (unsigned) |
0 |
4 |
− |
− |
− |
17 |
bcs |
dsp11 |
(C=1) |
BR |
branch if carry set |
0 |
5 |
− |
− |
− |
18 |
bhs |
dsp11 |
(C=1) |
BR |
branch if higher or same (unsigned) |
0 |
5 |
− |
− |
− |
19 |
bpl |
dsp11 |
(N=0) |
BR |
branch if plus or zero |
0 |
6 |
− |
− |
− |
20 |
bmi |
dsp11 |
(N=1) |
BR |
branch if minus |
0 |
7 |
− |
− |
− |
21 |
bvc |
dsp11 |
(V=0) |
BR |
branch if overflow clear |
0 |
8 |
− |
− |
− |
22 |
bvs |
dsp11 |
(V=1) |
BR |
branch if overflow set |
0 |
9 |
− |
− |
− |
23 |
bge |
dsp11 |
(N^V=0) |
BR |
branch if greater or equal (signed) |
0 |
10 |
− |
− |
− |
24 |
blt |
dsp11 |
(N^V=1) |
BR |
branch if less than (signed) |
0 |
11 |
− |
− |
− |
25 |
hadd |
Rd |
Rs |
RR |
half add |
0 |
14 |
0 |
− |
− |
26 |
hsub |
Rd |
Rs |
RR |
half subtract |
0 |
14 |
1 |
− |
− |
27 |
hmul |
Rd |
Rs |
RR |
half multiply |
0 |
14 |
2 |
− |
− |
28 |
hdiv |
Rd |
Rs |
RR |
half divide |
0 |
14 |
3 |
− |
− |
29 |
hneg |
Rd |
Rs |
RR |
half negate sign |
0 |
14 |
4 |
− |
− |
30 |
hhalf |
Rd |
Rs |
RR |
cast uint16 to half |
0 |
14 |
5 |
− |
− |
31 |
huint |
Rd |
Rs |
RR |
cast half to uint16 |
0 |
14 |
6 |
− |
− |
32 |
hfrac |
Rd |
Rs |
RR |
half obtain fraction |
0 |
14 |
7 |
− |
− |
33 |
hmvsg |
Rd |
Rs |
RR |
half move sign bit |
0 |
14 |
8 |
− |
− |
34 |
hsat |
Rd |
Rs |
RR |
half saturate infinite number |
0 |
14 |
9 |
− |
− |
35 |
hcmp |
Rd |
Rs |
RR |
half compare |
0 |
14 |
10 |
− |
− |
36 |
hdown |
Rd |
Rs |
RR |
half round down to zero |
0 |
14 |
11 |
− |
− |
37 |
mulur |
Rd |
Rs |
RR |
multiply unsigned reversal |
0 |
14 |
16 |
− |
− |
38 |
mulsr |
Rd |
Rs |
RR |
multiply signed reversal |
0 |
14 |
17 |
− |
− |
39 |
divur |
Rd |
Rs |
RR |
divide unsigned reversal |
0 |
14 |
18 |
− |
− |
40 |
divsr |
Rd |
Rs |
RR |
divide signed reversal |
0 |
14 |
19 |
− |
− |
41 |
csft |
Rd |
Rs |
RR |
rotate shift with c flag |
0 |
14 |
23 |
− |
− |
42 |
ldbx |
Rd |
Rs |
RR |
load data byte extended address |
0 |
14 |
28 |
- |
- |
43 |
stbx |
Rd |
Rs |
RR |
store data byte extended address |
0 |
14 |
29 |
- |
- |
44 |
ldwx |
Rd |
Rs |
RR |
load data word extended address |
0 |
14 |
30 |
- |
- |
45 |
stwx |
Rd |
Rs |
RR |
store data word extended address |
0 |
14 |
31 |
- |
- |
46 |
or |
Rd |
Rs |
RR |
bitwise or |
0 |
15 |
0 |
− |
− |
47 |
and |
Rd |
Rs |
RR |
bitwise and |
0 |
15 |
1 |
− |
− |
48 |
eor |
Rd |
Rs |
RR |
bitwise exclusive or |
0 |
15 |
2 |
− |
− |
49 |
mov |
Rd |
Rs |
RR |
move |
0 |
15 |
3 |
− |
− |
50 |
movtc |
Rc |
Rs |
RR |
move to control register |
0 |
15 |
4 |
− |
− |
51 |
movfc |
Rd |
Rc |
RR |
move from control register |
0 |
15 |
5 |
− |
− |
52 |
add |
Rd |
Rs |
RR |
add |
0 |
15 |
6 |
− |
− |
53 |
adc |
Rd |
Rs |
RR |
add with carry |
0 |
15 |
7 |
− |
− |
54 |
sub |
Rd |
Rs |
RR |
subtract |
0 |
15 |
8 |
− |
− |
55 |
sbb |
Rd |
Rs |
RR |
subtract with borrow |
0 |
15 |
9 |
− |
− |
56 |
cmp |
Rd |
Rs |
RR |
compare |
0 |
15 |
10 |
− |
− |
57 |
cmb |
Rd |
Rs |
RR |
compare with borrow |
0 |
15 |
11 |
− |
− |
58 |
ldb |
Rd |
Rs |
RR |
load data byte |
0 |
15 |
12 |
− |
− |
59 |
stb |
Rd |
Rs |
RR |
store data byte |
0 |
15 |
13 |
− |
− |
60 |
ldw |
Rd |
Rs |
RR |
load data word |
0 |
15 |
14 |
− |
− |
61 |
stw |
Rd |
Rs |
RR |
store data word |
0 |
15 |
15 |
− |
− |
62 |
lsft |
Rd |
Rn |
RR |
logical shift |
0 |
15 |
16 |
− |
− |
63 |
asft |
Rd |
Rn |
RR |
arithmetical shift |
0 |
15 |
17 |
− |
− |
64 |
ldwsp |
Rd |
Rn |
RR |
load data word sp relative |
0 |
15 |
18 |
− |
− |
65 |
stwsp |
Rn |
Rd |
RR |
store data word sp relative |
0 |
15 |
19 |
− |
− |
66 |
mulu |
Rd |
Rs |
RR |
multiply unsigned |
0 |
15 |
20 |
− |
− |
67 |
muls |
Rd |
Rs |
RR |
multiply signed |
0 |
15 |
21 |
− |
− |
68 |
divu |
Rd |
Rs |
RR |
divide unsigned |
0 |
15 |
22 |
− |
− |
69 |
divs |
Rd |
Rs |
RR |
divide signed |
0 |
15 |
23 |
− |
− |
70 |
sbbz |
Rd |
− |
R |
subtract zero with borrow |
0 |
15 |
28 |
0 |
− |
71 |
cmbz |
Rd |
− |
R |
compare zero with borrow |
0 |
15 |
28 |
1 |
− |
72 |
adcz |
Rd |
− |
R |
add zero with carry |
0 |
15 |
29 |
6 |
− |
73 |
jmp |
Rn |
− |
R |
jump |
0 |
15 |
30 |
0 |
− |
74 |
jalw |
Rn |
− |
R |
jump and link word stack |
0 |
15 |
30 |
1 |
− |
75 |
sesrl |
imm3 |
− |
R |
set sr low byte |
0 |
15 |
30 |
2 |
− |
76 |
sesrh |
imm3 |
− |
R |
set sr high byte |
0 |
15 |
30 |
3 |
− |
77 |
clsrl |
imm3 |
− |
R |
clear sr low byte |
0 |
15 |
30 |
4 |
− |
78 |
clsrh |
imm3 |
− |
R |
clear sr high byte |
0 |
15 |
30 |
5 |
− |
79 |
neg |
Rd |
− |
R |
negate sign |
0 |
15 |
31 |
0 |
− |
80 |
not |
Rd |
− |
R |
bitwise not |
0 |
15 |
31 |
1 |
− |
81 |
cendw |
Rd |
− |
R |
convert endian word |
0 |
15 |
31 |
2 |
− |
82 |
exsgw |
Rd |
− |
R |
extend sign bit word |
0 |
15 |
31 |
3 |
− |
83 |
pushw |
Rs |
− |
R |
push register word on stack |
0 |
15 |
31 |
4 |
− |
84 |
popw |
Rd |
− |
R |
pop register word from stack |
0 |
15 |
31 |
5 |
− |
85 |
pushcw |
Rc |
− |
R |
push control register word on stack |
0 |
15 |
31 |
6 |
− |
86 |
popcw |
Rc |
− |
R |
pop control register word from stack |
0 |
15 |
31 |
7 |
− |
87 |
ori |
Rd |
imm8 |
RI |
bitwise or immediate |
1 |
0 |
− |
− |
− |
88 |
andi |
Rd |
imm8 |
RI |
bitwise and immediate |
1 |
1 |
− |
− |
− |
89 |
eori |
Rd |
imm8 |
RI |
bitwise exclusive or immediate |
1 |
2 |
− |
− |
− |
90 |
addi |
Rd |
imm8 |
RI |
add immediate |
1 |
3 |
− |
− |
− |
91 |
subi |
Rd |
imm8 |
RI |
subtract immediate |
1 |
4 |
− |
− |
− |
92 |
cmpi |
Rd |
imm8 |
RI |
compare immediate |
1 |
5 |
− |
− |
− |
93 |
ldbiu |
Rd |
imm8 |
RI |
load data immediate unsigned byte |
1 |
6 |
− |
− |
− |
94 |
ldbil |
Rd |
imm8 |
RI |
load data immediate low byte |
1 |
7 |
− |
− |
− |
95 |
ldbih |
Rd |
imm8 |
RI |
load data immediate high byte |
1 |
8 |
− |
− |
− |
96 |
ldcl |
Rc |
imm8 |
RI |
load data immediate control register low byte |
1 |
9 |
− |
− |
− |
97 |
ldch |
Rc |
imm8 |
RI |
load data immediate control register high byte |
1 |
10 |
− |
− |
− |
98 |
lsfti |
Rd |
imm8 |
RI |
logical shift immediate |
1 |
11 |
− |
− |
− |
99 |
asfti |
Rd |
imm8 |
RI |
arithmetical shift immediate |
1 |
12 |
− |
− |
− |
100 |
csfti |
Rd |
imm8 |
RI |
rotate shift with c flag immediate |
1 |
13 |
− |
− |
− |
命令セット
各命令をアルファベット昇順で説明します。
adc (add with carry)
- 書式: adc Rd,Rs
- 動作: Rd’=Rd+Rs+Sr[C]
- 2つのレジスタ値と状態レジスタsrのCフラグ値を加算して、Rdに書き戻す。
- 複数レジスタ加算実行時のゼロ判定が可能な様に、直前のSr[Z]フラグ値を継承する。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=Rd’[16]
- V=Rd[15]×Rs[15]×(!Rd’[15])+(!Rd[15])×(!Rs[15])×Rd’[15]
- Z=(Rd’=0)×Sr[Z]
adcz (add zero with carry)
- 書式: adcz Rd
- 動作: Rd’=Rd+0+Sr[C]
- レジスタ値と状態レジスタsrのCフラグ値を加算して、Rdに書き戻す。
- 複数レジスタ加算実行時のゼロ判定が可能な様に、直前のSr[Z]フラグ値を継承する。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=Rd’[16]
- V=(!Rd[15])×Rd’[15]
- Z=(Rd’=0)×Sr[Z]
add (add)
- 書式: add Rd,Rs
- 動作: Rd’=Rd+Rs
- 汎用レジスタRd,Rsを加算して、Rdに書き戻す。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=Rd’[16]
- V=Rd[15]×Rs[15]×(!Rd’[15])+(!Rd[15])×(!Rs[15])×Rd’[15]
- Z=(Rd’=0)
addi (add immediate)
- 書式: addi Rd,imm8
- 動作: Rd’=Rd+uint8(imm8)
- 汎用レジスタRdに即値imm8(8ビット符号無整数)を加算して、Rdに書き戻す。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=Rd’[16]
- V=(!Rd[15])×Rd’[15]
- Z=(Rd’=0)
and (bitwise and)
- 書式: and Rd,Rs
- 動作: Rd’=Rd&Rs
- 汎用レジスタRd,Rsをビット毎論理AND演算して、Rdに書き戻す。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=0
- V=0
- Z=(Rd’=0)
andi (bitwise and immediate)
- 書式: andi Rd,imm8
- 動作: Rd’=Rd&uint8(imm8)
- 汎用レジスタRdと即値imm8を論理AND演算して、Rdに書き戻す。
- imm8は8ビット符号無整数なので、Rd’の上位8ビットは常に0x00となる。
- 実行: 1サイクル
- 状態:
asft (arithmetical shift)
- 書式: asft Rd,Rn
- 動作: Rd’=int16(Rd)<<int5(Rn[4:0])
- 汎用レジスタ値Rdを算術シフト演算して、Rdに書き戻す。
- シフト量はRnレジスタ値の下位5ビットを5ビット符号付整数と見て、int5(Rn[4:0])>0なら左シフト、int5(Rn[4:0])<0なら右シフト。
- シフト可能な範囲は−16〜15ビット。
- int5(Rn[4:0])=0だとRdは変化しない。
- Rnの上位11ビットは無視。
- 算術シフト演算では、Rdの16ビット以上のビットは符号拡張、0ビット未満のビットは0と見なす。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=(int5(Rn)≧0)?Rd’[16]:Rd’[−1]
- V=(int5(Rn)<0)?0:Rd’[16]^Rd’[15]
- Z=(Rd’=0)
asfti (arithmetical shift immediate)
- 書式: asfti Rd,imm8
- 動作: Rd’=int16(Rd)<<int5(imm8)
- 汎用レジスタ値Rdを算術シフト演算して、Rdに書き戻す。
- シフト量は即値imm8の下位5ビットを5ビット符号付整数と見て、int5(imm8)>0なら左シフト、int5(imm8)<0なら右シフト。
- シフト可能な範囲は−16〜15ビット。
- int5(imm8)=0だとRdは変化しない。
- imm8の上位3ビットは無視。
- 算術シフト演算では、Rdの16ビット以上のビットは符号拡張、0ビット未満のビットは0と見なす。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=(int5(imm8)≧0)?Rd’[16]:Rd’[−1]
- V=(int5(imm8)<0)?0:Rd’[16]^Rd’[15]
- Z=(Rd’=0)
bcc (branch if carry clear)
- 書式: bcc dsp11
- dsp11は11ビット符号付ディスプレースメント。
- 動作: if (!Sr[C]) Pc’=Pc+int11(dsp11)×2
- 分岐先アドレスは常に偶数のため、dsp11は最下位ビットが省略されており、2倍してアドレス計算に用いる。
- 条件不成立時は、次の命令を実行する。
- 直前命令が「cmp Rd,Rs」の場合、Rd,Rsを符号無整数とみなして、Rd≧Rsの時に条件!Sr[C]が成立する。
- 命令コードはbhs命令と同じ。
- 実行: 1/2サイクル(条件不成立時/成立時)
- 状態: 変化しない。
bcs (branch if carry set)
- 書式: bcs dsp11
- dsp11は11ビット符号付ディスプレースメント。
- 動作: if (Sr[C]) Pc’=Pc+int11(dsp11)×2
- 分岐先アドレスは常に偶数のため、dsp11は最下位ビットが省略されており、2倍してアドレス計算に用いる。
- 条件不成立時は、次の命令を実行する。
- 直前命令が「cmp Rd,Rs」の場合、Rd,Rsを符号無整数とみなして、Rd<Rsの時に条件Sr[C]が成立する。
- 命令コードはblo命令と同じ。
- 実行: 1/2サイクル(条件不成立時/成立時)
- 状態: 変化しない。
beq (branch if equal)
- 書式: beq dsp11
- dsp11は11ビット符号付ディスプレースメント。
- 動作: if (Sr[Z]) Pc’=Pc+int11(dsp11)×2
- 分岐先アドレスは常に偶数のため、dsp11は最下位ビットが省略されており、2倍してアドレス計算に用いる。
- 条件不成立時は、次の命令を実行する。
- 実行: 1/2サイクル(条件不成立時/成立時)
- 状態: 変化しない。
bge (branch if greater or equal;signed)
- 書式: bge dsp11
- dsp11は11ビット符号付ディスプレースメント。
- 動作: if (!(Sr[N]^Sr[V])) Pc’=Pc+int11(dsp11)×2
- 分岐先アドレスは常に偶数のため、dsp11は最下位ビットが省略されており、2倍してアドレス計算に用いる。
- 条件不成立時は、次の命令を実行する。
- 直前命令が「cmp Rd,Rs」の場合、Rd,Rsを符号付整数とみなして、Rd≧Rsの時に条件!Sr[N]^Sr[V]が成立する。
- 実行: 1/2サイクル(条件不成立時/成立時)
- 状態: 変化しない。
bhs (branch if higher or same;unsigned)
- 書式: bhs dsp11
- dsp11は11ビット符号付ディスプレースメント。
- 動作: if (!Sr[C]) Pc’=Pc+int11(dsp11)×2
- 分岐先アドレスは常に偶数のため、dsp11は最下位ビットが省略されており、2倍してアドレス計算に用いる。
- 条件不成立時は、次の命令を実行する。
- 直前命令が「cmp Rd,Rs」の場合、Rd,Rsを符号無整数とみなして、Rd≧Rsの時に条件!Sr[C]が成立する。
- 命令コードはbcc命令と同じ。
- 実行: 1/2サイクル(条件不成立時/成立時)
- 状態: 変化しない。
blo (branch if lower;unsigned)
- 書式: blo dsp11
- dsp11は11ビット符号付ディスプレースメント。
- 動作: if (Sr[C]) Pc’=Pc+int11(dsp11)×2
- 分岐先アドレスは常に偶数のため、dsp11は最下位ビットが省略されており、2倍してアドレス計算に用いる。
- 条件不成立時は、次の命令を実行する。
- 直前命令が「cmp Rd,Rs」の場合、Rd,Rsを符号無整数とみなして、Rd<Rsの時に条件Sr[C]が成立する。
- 命令コードはbcs命令と同じ。
- 実行: 1/2サイクル(条件不成立時/成立時)
- 状態: 変化しない。
blt (branch if less than;signed)
- 書式: blt dsp11
- dsp11は11ビット符号付ディスプレースメント。
- 動作: if (Sr[N]^Sr[V]) Pc’=Pc+int11(dsp11)×2
- 分岐先アドレスは常に偶数のため、dsp11は最下位ビットが省略されており、2倍してアドレス計算に用いる。
- 条件不成立時は、次の命令を実行する。
- 直前命令が「cmp Rd,Rs」の場合、Rd,Rsを符号付整数とみなして、Rd<Rsの時に条件Sr[N]^Sr[V]が成立する。
- 実行: 1/2サイクル(条件不成立時/成立時)
- 状態: 変化しない。
bmi (branch if minus)
- 書式: bmi dsp11
- dsp11は11ビット符号付ディスプレースメント。
- 動作: if (Sr[N]) Pc’=Pc+int11(dsp11)×2
- 分岐先アドレスは常に偶数のため、dsp11は最下位ビットが省略されており、2倍してアドレス計算に用いる。
- 条件不成立時は、次の命令を実行する。
- 実行: 1/2サイクル(条件不成立時/成立時)
- 状態: 変化しない。
bne (branch if not equal)
- 書式: bne dsp11
- dsp11は11ビット符号付ディスプレースメント。
- 動作: if (!Sr[Z]) Pc’=Pc+int11(dsp11)×2
- 分岐先アドレスは常に偶数のため、dsp11は最下位ビットが省略されており、2倍してアドレス計算に用いる。
- 条件不成立時は、次の命令を実行する。
- 実行: 1/2サイクル(条件不成立時/成立時)
- 状態: 変化しない。
bpl (branch if plus or zero)
- 書式: bpl dsp11
- dsp11は11ビット符号付ディスプレースメント。
- 動作: if (Sr[N]) Pc’=Pc+int11(dsp11)×2
- 分岐先アドレスは常に偶数のため、dsp11は最下位ビットが省略されており、2倍してアドレス計算に用いる。
- 条件不成立時は、次の命令を実行する。
- 実行: 1/2サイクル(条件不成立時/成立時)
- 状態: 変化しない。
bra (branch always)
- 書式: bra dsp11
- dsp11は11ビット符号付ディスプレースメント。
- 動作: Pc’=Pc+int11(dsp11)×2
- 分岐先アドレスは常に偶数のため、dsp11は最下位ビットが省略されており、2倍してアドレス計算に用いる。
- 実行: 2サイクル
- 状態: 変化しない。
brn (branch never)
- 書式: brn
- 動作: なし
- 分岐しない分岐命令なので、動作としてはnop命令と同じです。
- スーパスケイラ版CPUでは、必ず、スロット0に単独で発行され、他の命令と並列実行されることの無い命令です(詳細はこちら)。
- 実行: 1サイクル
- 状態: 変化しない。
bvc (branch if overflow clear)
- 書式: bvc dsp11
- dsp11は11ビット符号付ディスプレースメント。
- 動作: if (Sr[V]) Pc’=Pc+int11(dsp11)×2
- 分岐先アドレスは常に偶数のため、dsp11は最下位ビットが省略されており、2倍してアドレス計算に用いる。
- 条件不成立時は、次の命令を実行する。
- 実行: 1/2サイクル(条件不成立時/成立時)
- 状態: 変化しない。
bvs (branch if overflow set)
- 書式: bvs dsp11
- dsp11は11ビット符号付ディスプレースメント。
- 動作: if (Sr[V]) Pc’=Pc+int11(dsp11)×2
- 分岐先アドレスは常に偶数のため、dsp11は最下位ビットが省略されており、2倍してアドレス計算に用いる。
- 条件不成立時は、次の命令を実行する。
- 実行: 1/2サイクル(条件不成立時/成立時)
- 状態: 変化しない。
cendw (convert endian word)
- 書式: cendw Rd
- Rdは汎用レジスタ(r0〜r7)。
- 別名cendも使用可能。
- 動作: Rd’={Rd[7:0],Rd[15:8]}
- 汎用レジスタRdのエンディアンを変換(BE⇔LE)して、Rdに書き戻す。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=0
- V=0
- Z=(Rd’=0)
clsrh (clear sr high byte's bit)
- 書式: clsrh imm3
- 動作: Sr[8+imm3]=0
- 状態レジスタsrの第(8+imm3)ビットを0にクリアする。
- 実行: 1サイクル
- 状態: 変化しない
clsrl (clear sr low byte's bit)
- 書式: clsrl imm3
- 動作: Sr[imm3]=0
- 状態レジスタsrの第imm3ビットを0にクリアする。
- 実行: 1サイクル
- 状態: 変化しない
- ただし、imm3が演算フラグを指す場合は、そのフラグがクリアされる。
cmb (compare with borrow)
- 書式: cmb Rd,Rs
- 動作: Rd−Rs−Sr[C]
- 2つのレジスタ値と状態レジスタsrのCフラグ値を減算して、状態レジスタの各フラグを更新する。
- 複数レジスタ比較実行時のゼロ判定が可能な様に、直前のSr[Z]フラグ値を継承する。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=!Rd’[16]
- V=Rd[15]×(!Rs[15])×(!Rd’[15])+(!Rd[15])×Rs[15]×Rd’[15]
- Z=(Rd’=0)×Sr[Z]
cmbz (compare zero with borrow)
- 書式: cmbz Rd
- 動作: Rd−0−Sr[C]
- レジスタ値と状態レジスタsrのCフラグ値を減算して、状態レジスタの各フラグを更新する。
- 複数レジスタ比較実行時のゼロ判定が可能な様に、直前のSr[Z]フラグ値を継承する。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=!Rd’[16]
- V=Rd[15]×(!Rd’[15])
- Z=(Rd’=0)×Sr[Z]
cmp (compare)
- 書式: cmp Rd,Rs
- 動作: Rd−Rs
- 汎用レジスタRdからRsを減算して、状態レジスタの各フラグを更新する。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=!Rd’[16]
- V=Rd[15]×(!Rs[15])×(!Rd’[15])+(!Rd[15])×Rs[15]×Rd’[15]
- Z=(Rd’=0)
cmpi (compare immediate)
- 書式: cmpi Rd,imm8
- Rdは汎用レジスタ(r0〜r7)。imm8は符号無8ビット即値。
- 動作: Rd−uint8(imm8)
- 汎用レジスタRdから即値imm8(8ビット符号無整数)を減算して、状態レジスタの各フラグを更新する。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=!Rd’[16]
- V=Rd[15]×(!Rd’[15])
- Z=(Rd’=0)
csft (rotate shift with c flag)
- 書式: csft Rd,Rn
- 動作: {Sr’[C],Rd’}={Sr[C],uint16(Rd)}<<int5(Rn[4:0])
- 汎用レジスタ値Rdと状態レジスタsrのキャリCフラグ値を回転シフト演算して、Rdに書き戻す。
- シフト量はRnレジスタ値の下位5ビットを5ビット符号付整数と見て、int5(Rn[4:0])>0なら左シフト、int5(Rn[4:0])<0なら右シフト。
- シフト可能な範囲は−16〜15ビット。
- int5(Rn[4:0])=0だとRdは変化しない。
- Rnの上位11ビットは無視。
- 回転シフト演算では、累積シフトビット数が17の倍数となると、Rd,Sr[C]に関して元の値に戻る。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=(int5(Rn)≧0)?Rd’[16]:Rd’[−1]
- V=0
- Z=(Rd’=0)
csfti (rotate shift with c flag immediate)
- 書式: csfti Rd,imm8
- 動作: {Sr’[C],Rd’}={Sr[C],uint16(Rd)}<<int5(imm8)
- 汎用レジスタ値Rdと状態レジスタsrのキャリCフラグ値を回転シフト演算して、Rdに書き戻す。
- シフト量は即値imm8の下位5ビットを5ビット符号付整数と見て、int5(imm8)>0なら左シフト、int5(imm8)<0なら右シフト。
- シフト可能な範囲は−16〜15ビット。
- int5(imm8)=0だとRdは変化しない。
- imm8の上位3ビットは無視。
- 回転シフト演算では、累積シフトビット数が17の倍数となると、Rd,Sr[C]に関して元の値に戻る。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=(int5(imm8)≧0)?Rd’[16]:Rd’[−1]
- V=0
- Z=(Rd’=0)
divlq (load quotient and remainder)
- 書式: divlq
- 動作: R0:R1=Quo; if (Sr[DR]) R2:R3=Rem
- 32ビット除算を実行するdivlu命令または、divls命令の演算結果(商Quoおよび剰余Rem)を取得する。
- 演算結果はいずれも32ビット長なので、2対のレジスタペアに取得する。
- レジスタペアは、商がR0:R1、剰余がR2:R3に固定で、偶数レジスタが上位、奇数レジスタが下位データとなる。
- この命令では、除算自体は実行しないので、予めdivls命令またはdivlu命令を実行後に本命令を実行する必要がある。
-
例)
sesrh 4 // DR=1(剰余を求める)
ldwi r0,0x89ab // r0:r1=被除数
ldwi r1,0xcdef
ldwi r2,0x0123 // r2:r3=除数
ldwi r3,0x4567
divlu // r0:r1÷r2:r3
divlq // 結果の取得(r0:r1=商、r2:r3=剰余)
- この時点で、r0:r1に商(Quo=0x89abcdef÷0x01234567)、r2:r3に剰余(Rem=0x89abcdef%0x01234567)が格納される。
- 状態レジスタsrのDRビット=0の場合には、剰余は取得せずR2:R3は変化しない。
- divls命令またはdivlu命令実行の直後に本命令を実行すると、コプロセッサ内の除算が終了するまで待ってから、演算結果を取得する。
- divls命令または、divlu命令と連続して実行した場合の実行サイクル数は、合わせて14〜17[サイクル]となる(DR=0の場合は2サイクル短縮)。
- 除算コプロセッサ搭載時のみ有効な命令。
- 実行: 2/4サイクル以上(DR=0/1)
- 状態: 変化しない。
divlqr (load quotient and remainder reversal)
- 書式: divlqr
- 動作: R0:R1=Quo; if (!Sr[DR]) R2:R3=Rem
- 32ビット除算を実行するdivlu命令または、divls命令の演算結果(商Quoおよび剰余Rem)を取得する。
- 演算結果はいずれも32ビット長なので、2対のレジスタペアに取得する。
- レジスタペアは、商がR0:R1、剰余がR2:R3に固定で、偶数レジスタが上位、奇数レジスタが下位データとなる。
- この命令では、除算自体は実行しないので、予めdivls命令またはdivlu命令を実行後に本命令を実行する必要がある。
- 状態レジスタsrのDRビット=1の場合には、剰余は取得せずR2:R3は変化しない。
- divlq命令とは、DRビットの意味が反転する(→ reversal)。
- divls命令またはdivlu命令実行の直後に本命令を実行すると、コプロセッサ内の除算が終了するまで待ってから、演算結果を取得する。
- divls命令または、divlu命令と連続して実行した場合の実行サイクル数は、合わせて14〜17[サイクル]となる(DR=1の場合は2サイクル短縮)。
- 除算コプロセッサ搭載時のみ有効な命令。
- 実行: 2/4サイクル以上(DR=1/0)
- 状態: 変化しない。
divlr (restore quotient and remainder)
- 書式: divlr
- 動作: Quo=R0:R1; if (Sr[DR]) Rem=R2:R3
- 除算コプロセッサの演算結果レジスタ(商Quoおよび剰余Rem)にデータを書き戻す。
- 演算結果レジスタはいずれも32ビット長なので、2対のレジスタペアから転送する。
- レジスタペアは、商がR0:R1、剰余がR2:R3に固定で、偶数レジスタが上位、奇数レジスタが下位データとなる。
- 状態レジスタsrのDRビット=0の場合には、剰余は転送しない。
- 割り込み処理ルーチン内などで除算命令を使用する場合、通常処理で計算した結果を保存する必要があるため、divlq命令とセットで使用して、演算結果レジスタの退避・回復に使用する。
- 除算コプロセッサ搭載時のみ有効な命令。
- 実行: 1/2サイクル(DR=0/1)
- 状態: 変化しない。
divlrr (restore quotient and remainder reversal)
- 書式: divlrr
- 動作: Quo=R0:R1; if (!Sr[DR]) Rem=R2:R3
- 除算コプロセッサの演算結果レジスタ(商Quoおよび剰余Rem)にデータを書き戻す。
- 演算結果レジスタはいずれも32ビット長なので、2対のレジスタペアから転送する。
- レジスタペアは、商がR0:R1、剰余がR2:R3に固定で、偶数レジスタが上位、奇数レジスタが下位データとなる。
- 状態レジスタsrのDRビット=1の場合には、剰余は転送しない。
- divlr命令とは、DRビットの意味が反転する(→ reversal)。
- 割り込み処理ルーチン内などで除算命令を使用する場合、通常処理で計算した結果を保存する必要があるため、divlqr命令とセットで使用して、演算結果レジスタの退避・回復に使用する。
- 除算コプロセッサ搭載時のみ有効な命令。
- 実行: 1/2サイクル(DR=1/0)
- 状態: 変化しない。
divls (divide long signed)
- 書式: divls
- 動作: int32(R0:R1)÷R2:R3
- 32ビット符号付除算を実行する。
- 被除数・除数はいずれも32ビット長なので、2対のレジスタペアで指定する。
- レジスタペアは被除数がR0:R1、除数がR2:R3に固定で、偶数レジスタが上位、奇数レジスタが下位データとなる。
- 本命令は演算を実行開始するだけなので、結果を取得するためにはdivlq命令または、divlqr命令を実行する必要がある。
- divls命令とdivlq命令/divlqr命令を連続して実行した場合のサイクル数は合わせて14〜17[サイクル]となる(剰余を取得しない場合は2サイクル短縮)。
- ゼロ除算(R2:R3=0)は結果が正しくないため実行禁止。
- 除算コプロセッサ搭載時のみ有効な命令。
- 実行: 3サイクル
- 状態: 変化しない。
divlu (divide long unsigned)
- 書式: divlu
- 動作: uint32(R0:R1)÷R2:R3
- 32ビット符号無除算を実行する。
- 被除数・除数はいずれも32ビット長なので、2対のレジスタペアで指定する。
- レジスタペアは被除数がR0:R1、除数がR2:R3に固定で、偶数レジスタが上位、奇数レジスタが下位データとなる。
- 本命令は演算を実行開始するだけなので、結果を取得するためにはdivlq命令または、divlqr命令を実行する必要がある。
- divlu命令とdivlq命令/divlqr命令を連続して実行した場合のサイクル数は合わせて14サイクルとなる(剰余を取得しない場合は2サイクル短縮)。
- ゼロ除算(R2:R3=0)は結果が正しくないため実行禁止。
- 除算コプロセッサ搭載時のみ有効な命令。
- 実行: 3サイクル
- 状態: 変化しない。
divs (divide signed)
- 書式: divs Rd,Rs
- 動作: Rd’=int16(Rd)÷Rs; if (Sr[DR]) Rs’=int16(Rd)%Rs
- 16ビット符号付除算を実行する。
- 状態レジスタsrのDRビット=0の場合には、剰余は取得せずRsは変化しない。
- ゼロ除算(Rs=0)は結果が正しくないため実行禁止。
- 除算コプロセッサ搭載時のみ有効な命令。
- 実行: ((6〜9)+DR)サイクル
- 状態: 変化しない。
divsr (divide signed reversal)
- 書式: divsr Rd,Rs
- 動作: Rd’=int16(Rd)÷Rs; if (!Sr[DR]) Rs’=int16(Rd)%Rs
- 16ビット符号付除算を実行する。
- 状態レジスタsrのDRビット=1の場合には、剰余は取得せずRsは変化しない。
- divs命令とは、DRビットの意味が反転する(→ reversal)。
- ゼロ除算(Rs=0)は結果が正しくないため実行禁止。
- 除算コプロセッサ搭載時のみ有効な命令。
- 実行: ((6〜9)+(1−DR))サイクル
- 状態: 変化しない。
divu (divide unsigned)
- 書式: divu Rd,Rs
- 動作: Rd’=uint16(Rd)÷Rs; if (Sr[DR]) Rs’=uint16(Rd)%Rs
- 16ビット符号無除算を実行する。
- 状態レジスタsrのDRビット=0の場合には、剰余は取得せずRsは変化しない。
- ゼロ除算(Rs=0)は結果が正しくないため実行禁止。
- 除算コプロセッサ搭載時のみ有効な命令。
- 実行: (6+DR)サイクル
- 状態: 変化しない。
divur (divide unsigned reversal)
- 書式: divur Rd,Rs
- 動作: Rd’=uint16(Rd)÷Rs; if (!Sr[DR]) Rs’=uint16(Rd)%Rs
- 16ビット符号無除算を実行する。
- 状態レジスタsrのDRビット=1の場合には、剰余は取得せずRsは変化しない。
- divu命令とは、DRビットの意味が反転する(→ reversal)。
- ゼロ除算(Rs=0)は結果が正しくないため実行禁止。
- 除算コプロセッサ搭載時のみ有効な命令。
- 実行: (6+(1−DR))サイクル
- 状態: 変化しない。
eor (bitwise exclusive or)
- 書式: eor Rd,Rs
- 動作: Rd’=Rd^Rs
- 汎用レジスタRd,Rsをビット毎論理EOR(Exclusive OR)演算して、Rdに書き戻す。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=0
- V=0
- Z=(Rd’=0)
eori (bitwise exclusive or immediate)
- 書式: eori Rd,imm8
- Rdは汎用レジスタ(r0〜r7)。imm8は符号無8ビット即値。
- 動作: Rd’=Rd^uint8(imm8)
- 汎用レジスタRdと即値imm8(8ビット符号無整数)をビット毎論理EOR(Exclusive OR)演算して、Rdに書き戻す。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=0
- V=0
- Z=(Rd’=0)
exsgw (extend sign bit word)
- 書式: exsgw Rd
- Rdは汎用レジスタ(r0〜r7)。
- 別名exsgも使用可能。
- 動作: Rd’=int8(Rd[7:0])
- 汎用レジスタRdの下位8ビットデータを16ビットに符号拡張して、Rdに書き戻す。
- 元のRdの上位8ビットは無視して、符号拡張によって上書きする。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=0
- V=0
- Z=(Rd’=0)
hadd (half add)
- 書式: hadd Rd,Rs
- 動作: Rd’=Rd+Rs
- 汎用レジスタRd,Rsをhalf型(半精度浮動小数)と見て加算し、Rdに書き戻す。
- H-FPU搭載時のみ有効な命令。
- 実行: (3〜8)サイクル
- 状態: 変化しない。
hcmp (half compare)
- 書式: hcmp Rd,Rs
- 動作: Rd−Rs
- 汎用レジスタRd,Rsをhalf型(半精度浮動小数)と見て減算し、状態レジスタの各フラグを更新する。
- Nフラグ: Rd−Rs=NaNまたは、Rd−Rs<0の場合にN=1となる。それ以外のケースではN=0。
- Cフラグ: Rd−Rs=±0または、Rd=Rs=±INF、Rd=Rs=NaNの場合にC=1となる。それ以外のケースではC=0。
- Vフラグ: Rd−Rs=NaNの時、V=1となる。それ以外のケースではV=0。
- Zフラグ: Rd−Rs=±0の時、Z=1となる。それ以外のケースではZ=0。
- 命令実行後、Rd,Rsレジスタ値は変化しない。
- H-FPU搭載時のみ有効な命令。
- 実行: (3〜8)サイクル
- 状態:
- N=(Rd−Rs=NaN)+(Rd−Rs<0)
- C=(Rd−Rs=±0)+(Rd=Rs=±INF)+(Rd=Rs=NaN)
- V=(Rd−Rs=NaN)
- Z=(Rd−Rs=±0)
hdiv (half divide)
- 書式: hdiv Rd,Rs
- 動作: Rd’=Rd÷Rs
- 汎用レジスタRd,Rsをhalf型(半精度浮動小数)と見て除算し、Rdに書き戻す。
- H-FPU搭載時のみ有効な命令。
- 実行: (6〜7)サイクル
- 状態: 変化しない。
hdown (half round down to zero)
- 書式: hdown Rd,Rs
- 動作: Rd’=sgn(Rs)×floor(abs(Rs))
- 汎用レジスタRsをhalf型(半精度浮動小数)と見て、Rsの小数点以下をゼロ方向へ切り捨てた値をRdに転送する。
- 言い換えると、Rsをhalf型のまま、整数に変換してRdに転送する。
- Rsの符号はRdでも保存される。動作式の通り、本命令の動作はfloor()関数とは異なることに注意。
- H-FPU搭載時のみ有効な命令。
- 実行: 2サイクル
- 状態: 変化しない。
hfrac (half obtain fraction)
- 書式: hfrac Rd,Rs
- 動作: Rd=uint16(abs(Rs)×65,536)
- 汎用レジスタRsをhalf型(半精度浮動小数)と見て、小数点以下16ビットバイナリ値をRdに転送する。
- Rs=±INFまたはRs=NaNだった場合、Rd=0が返る。
- 例)Rs=half (1.25)だった場合、hfrac命令実行後のRd=0x4000。
- Rd÷65,536が元の小数値なので、0x4000÷65,536=0.25であり、Rsの小数点以下の数値が得られた。
- H-FPU搭載時のみ有効な命令。
- 実行: (3〜7)サイクル
- 状態: 変化しない。
hhalf (cast uint16 to half)
- 書式: hhalf Rd,Rs
- 動作: Rd=half(Rs)
- 汎用レジスタRsをuint16型(16ビット符号無整数)と見て、half型(半精度浮動小数)にキャストしてRdに転送する。
- Rs(uint16)の冗長ビットは無視して切り捨てる。Rs>65,504の場合はRs=half (65,504)となる。
- H-FPU搭載時のみ有効な命令。
- 実行: (3〜5)サイクル
- 状態: 変化しない。
hmul (half multiply)
- 書式: hmul Rd,Rs
- 動作: Rd’=Rd×Rs
- 汎用レジスタRd,Rsをhalf型(半精度浮動小数)と見て乗算し、Rdに書き戻す。
- H-FPU搭載時のみ有効な命令。
- 実行: (3〜4)サイクル
- 状態: 変化しない。
hmvsg (half move sign bit)
- 書式: hmvsg Rd,Rs
- 動作: Rd’=Rd×sgn(Rd)×sgn(Rs)
- 汎用レジスタRd,Rsをhalf型(半精度浮動小数)と見て、Rsの符号ビットをRdの符号ビットに転送する。
- Rdの符号ビット以外の意味に変化は無い。
- H-FPU搭載時のみ有効な命令。
- 実行: 2サイクル
- 状態: 変化しない。
hneg (half negate sign)
- 書式: hneg Rd,Rs
- 動作: Rd=−Rs
- 汎用レジスタRsをhalf型(半精度浮動小数)と見て、Rsの符号を反転してRdに転送する。
- H-FPU搭載時のみ有効な命令。
- 実行: 2サイクル
- 状態: 変化しない。
hsat (half saturate infinite number)
- 書式: hsat Rd,Rs
- 動作: Rd=(Rs=±INF)?±65,504:(Rs=−0)?0:Rs
- 汎用レジスタRsをhalf型(半精度浮動小数)と見て、無限大(±INF)を有限の絶対値最大値(65,504)に変換してRdに転送する。
- 大小比較などで扱いにくい負号付きゼロ値(−0)も、ゼロ(0)に縮退する。
- H-FPU搭載時のみ有効な命令。
- 実行: 2サイクル
- 状態: 変化しない。
hsub (half subtract)
- 書式: hsub Rd,Rs
- 動作: Rd’=Rd−Rs
- 汎用レジスタRd,Rsをhalf型(半精度浮動小数)と見て減算し、Rdに書き戻す。
- H-FPU搭載時のみ有効な命令。
- 実行: (3〜8)サイクル
- 状態: 変化しない。
huint (cast half to uint16)
- 書式: huint Rd,Rs
- 動作: Rd=uint16(abs(Rs))
- 汎用レジスタRsをhalf型(半精度浮動小数)と見て、Rsの絶対値abs (Rs)をuint16型(16ビット符号無整数)にキャストしてRdに転送する。
- 小数点以下の数値は切り捨てとなる。
- Rs=±INFの場合はRd=0、Rs=NaNの場合はRd=0x0040〜0xffc0が返る(NaN仮数部の左詰め、通常はRd=0x8000)。有限値範囲0〜65,504と重なっているので、huint命令実行前にRsの値を確認して場合分けが必要。
- H-FPU搭載時のみ有効な命令。
- 実行: (3〜7)サイクル
- 状態: 変化しない。
jalw (jump and link word stack)
- 書式: jalw Rn
- 動作: [--Sp]=uint16(Pc); Pc=Rn
- 現在のプログラムカウンタpcをスタックに積んだ後、汎用レジスタRnの指し示すアドレスへ分岐する。
- jalw命令実行時点で、Pcはjalw命令の次の命令アドレスを指し示しているため、分岐先でrtnw命令を実行することで、jalw命令の次命令に復帰できる。
- 別名jalも使用可能。
- 実行: 3サイクル
- 状態: 変化しない。
jmp (jump)
- 書式: jmp Rn
- 動作: Pc=Rn
- 実行: 2サイクル
- 状態: 変化しない。
ldb (load data byte)
- 書式: ldb Rd,[Rs]
- 動作: Rd=uint8([Rs])
- 汎用レジスタRsの指し示すアドレスから8ビットバイトデータを読み出して汎用レジスタRdに転送する。
- 読み出したデータは8ビット符号無整数なので、Rdの上位8ビットは常に0x00。
- 実行: 2サイクル
- 状態: 変化しない。
ldbx (load data byte extended address)
- 書式: ldbx Rd,[Tr:Rs]
- Rd,Rsは汎用レジスタ(r0〜r7)。Trは一時レジスタ。
- 動作: Rd=uint8([Tr:Rs])
- 一時レジスタtrを上位16ビット、汎用レジスタRsを下位16ビットとする32ビット拡張アドレスから8ビットバイトデータを読み出して汎用レジスタRdに転送する。
- 読み出したデータは8ビット符号無整数なので、Rdの上位8ビットは常に0x00。
- 実行: (N+1)サイクル
- 状態: 変化しない。
ldbih (load data immediate high byte)
- 書式: ldbih Rd,imm8
- Rdは汎用レジスタ(r0〜r7)。imm8は符号無8ビット即値。
- 別名ldihも使用可能。
- 動作: Rd’={imm8,Rd[7:0]}
- 汎用レジスタRdの上位8ビットに即値imm8を転送する。
- Rdの下位8ビットは変化しない。
- 実行: 1サイクル
- 状態: 変化しない。
ldbil (load data immediate low byte)
- 書式: ldbil Rd,imm8
- Rdは汎用レジスタ(r0〜r7)。imm8は符号無8ビット即値。
- 別名ldilも使用可能。
- 動作: Rd’={Rd[15:8],imm8}
- 汎用レジスタRdの下位8ビットに即値imm8を転送する。
- Rdの上位8ビットは変化しない。
- 実行: 1サイクル
- 状態: 変化しない。
ldbiu (load data immediate unsigned byte)
- 書式: ldbiu Rd,imm8
- Rdは汎用レジスタ(r0〜r7)。imm8は符号無8ビット即値。
- 別名ldiuも使用可能。
- 動作: Rd=uint8(imm8)
- 汎用レジスタRdに即値imm8を転送する。
- imm8を16ビットにゼロ拡張して転送するので、Rdの上位8ビットは常に0x00が転送される。
- 実行: 1サイクル
- 状態: 変化しない。
ldch (load data immediate control register high byte)
- 書式: ldch Rc,imm8
- Rcは制御レジスタ(sr,sp,iv,tr)。imm8は符号無8ビット即値。
- 動作: Rc’={imm8,Rc[7:0]}
- 制御レジスタRcの上位8ビットに即値imm8を転送する。
- Rcの下位8ビットは変化しない。
- 実行: 1サイクル
- 状態: 変化しない。
ldcl (load data immediate control register low byte)
- 書式: ldcl Rc,imm8
- Rcは制御レジスタ(sr,sp,iv,tr)。imm8は符号無8ビット即値。
- 動作: Rc’={Rc[15:8],imm8}
- 制御レジスタRcの下位8ビットに即値imm8を転送する。
- Rcの上位8ビットは変化しない。
- 実行: 1サイクル
- 状態: 変化しない。
- ただし、Rcが状態レジスタsrの場合は、imm8の値が状態フラグ(N,C,V,Z)にセットされる。
ldw (load data word)
- 書式: ldw Rd,[Rs]
- 動作: Rd=uint16([Rs])
- 汎用レジスタRsの指し示すアドレスから16ビットワードデータを読み出して汎用レジスタRdに転送する。
- Rsが奇数アドレスであってはならない。
- 実行: 2サイクル
- 状態: 変化しない。
ldwsp (load data word sp relative)
- 書式: ldwsp Rd,[Sp+Rn]
- Rd,Rnは汎用レジスタ(r0〜r7)。Spはスタックポインタ。
- 別名ldspも使用可能。
- 動作: Tr=Sp+Rn; Rd=uint16([Tr])
- スタックポインタspに汎用レジスタRnを加算したアドレスから、16ビットワードデータを読み出して汎用レジスタRdに転送する。
- Sp+Rnが奇数アドレスであってはならない。
- 一時レジスタtrを使用してデータを破壊する。
- 実行: 3サイクル
- 状態: 変化しない
ldwx (load data word extended address)
- 書式: ldwx Rd,[Tr:Rs]
- Rd,Rsは汎用レジスタ(r0〜r7)。Trは一時レジスタ。
- 動作: Rd=uint16([Tr:Rs])
- 一時レジスタtrを上位16ビット、汎用レジスタRsを下位16ビットとする32ビット拡張アドレスから16ビットワードデータを読み出して汎用レジスタRdに転送する。
- Rsが奇数アドレスであってはならない。
- 実行: (N+1)サイクル
- 状態: 変化しない。
lsft (logical shift)
- 書式: lsft Rd,Rn
- 動作: Rd’=uint16(Rd)<<int5(Rn[4:0])
- 汎用レジスタ値Rdを論理シフト演算して、Rdに書き戻す。
- シフト量はRnレジスタ値の下位5ビットを5ビット符号付整数と見て、int5(Rn[4:0])>0なら左シフト、int5(Rn[4:0])<0なら右シフト。
- シフト可能な範囲は−16〜15ビット。
- int5(Rn[4:0])=0だとRdは変化しない。
- Rnの上位11ビットは無視。
- 論理シフト演算では、Rdの15〜0ビット範囲外のビットは0と見なす。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=(int5(Rn)≧0)?Rd’[16]:Rd’[−1]
- V=(int5(Rn)<0)?0:Rd’[16]^Rd’[15]
- Z=(Rd’=0)
lsfti (logical shift immediate)
- 書式: lsfti Rd,imm8
- Rdは汎用レジスタ(r0〜r7)。imm8は符号無8ビット即値。
- 動作: Rd’=uint16(Rd)<<int5(imm8)
- 汎用レジスタ値Rdを論理シフト演算して、Rdに書き戻す。
- シフト量は即値imm8の下位5ビットを5ビット符号付整数と見て、int5(imm8)>0なら左シフト、int5(imm8)<0なら右シフト。
- シフト可能な範囲は−16〜15ビット。
- int5(imm8)=0だとRdは変化しない。
- imm8の上位3ビットは無視。
- 論理シフト演算では、Rdの15〜0ビット範囲外のビットは0と見なす。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=(int5(imm8)≧0)?Rd’[16]:Rd’[−1]
- V=(int5(imm8)<0)?0:Rd’[16]^Rd’[15]
- Z=(Rd’=0)
mov (move)
- 書式: mov Rd,Rs
- 動作: Rd=Rs
- 実行: 1サイクル
- 状態:
- N=Rd[15]
- C=0
- V=0
- Z=(Rd=0)
movfc (move from control register)
- 書式: movfc Rd,Rc
- Rdは汎用レジスタ(r0〜r7)、Rcは制御レジスタ(sr,pc,sp,iv,tr)。
- 動作: Rd=Rc
- 実行: 1サイクル
- 状態:
- N=Rd[15]
- C=0
- V=0
- Z=(Rd=0)
movtc (move to control register)
- 書式: movtc Rc,Rs
- Rcは制御レジスタ(sr,sp,iv,tr)、Rsは汎用レジスタ(r0〜r7)。
- 動作: Rc=Rs
- 実行: 1サイクル
- 状態:
- N=Rc[15]
- C=0
- V=0
- Z=(Rc=0)
- ただし、Rcが状態レジスタsrの場合は、転送した値が状態フラグ(N,C,V,Z)にセットされる。
muls (multiply signed)
- 書式: muls Rd,Rs
- 動作: Rd’=int16(Rd)×Rs; if (Sr[ML]) Rs’=(int16(Rd)×Rs)>>16
- 16×16=32ビット符号付乗算を実行する。
- 一般に16×16ビット乗算結果(積)は32ビット長となる。
- 状態レジスタsrのMLビット=0の場合には、Rdに積の下位16ビットが転送され、Rsは変化しない。
- 状態レジスタsrのMLビット=1の場合には、Rdに積の下位16ビット、Rsに上位16ビットが転送される。
- 乗算コプロセッサ搭載時のみ有効な命令。
- 実行: (1+ML)サイクル
- 状態: 変化しない。
mulsr (multiply signed reversal)
- 書式: mulsr Rd,Rs
- 動作: Rd’=int16(Rd)×Rs; if (!Sr[ML]) Rs’=(int16(Rd)×Rs)>>16
- 16×16=32ビット符号付乗算を実行する。
- 一般に16×16ビット乗算結果(積)は32ビット長となる。
- 状態レジスタsrのMLビット=1の場合には、Rdに積の下位16ビットが転送され、Rsは変化しない。
- 状態レジスタsrのMLビット=0の場合には、Rdに積の下位16ビット、Rsに上位16ビットが転送される。
- muls命令とは、MLビットの意味が反転する(→ reversal)。
- 乗算コプロセッサ搭載時のみ有効な命令。
- 実行: (1+(1−ML))サイクル
- 状態: 変化しない。
mulu (multiply unsigned)
- 書式: mulu Rd,Rs
- 動作: Rd’=uint16(Rd)×Rs; if (Sr[ML]) Rs’=(uint16(Rd)×Rs)>>16
- 16×16=32ビット符号無乗算を実行する。
- 一般に16×16ビット乗算結果(積)は32ビット長となる。
- 状態レジスタsrのMLビット=0の場合には、Rdに積の下位16ビットが転送され、Rsは変化しない。
- 状態レジスタsrのMLビット=1の場合には、Rdに積の下位16ビット、Rsに上位16ビットが転送される。
- 乗算コプロセッサ搭載時のみ有効な命令。
- 実行: (1+ML)サイクル
- 状態: 変化しない。
mulur (multiply unsigned reversal)
- 書式: mulur Rd,Rs
- 動作: Rd’=uint16(Rd)×Rs; if (!Sr[ML]) Rs’=(uint16(Rd)×Rs)>>16
- 16×16=32ビット符号無乗算を実行する。
- 一般に16×16ビット乗算結果(積)は32ビット長となる。
- 状態レジスタsrのMLビット=1の場合には、Rdに積の下位16ビットが転送され、Rsは変化しない。
- 状態レジスタsrのMLビット=0の場合には、Rdに積の下位16ビット、Rsに上位16ビットが転送される。
- mulu命令とは、MLビットの意味が反転する(→ reversal)。
- 乗算コプロセッサ搭載時のみ有効な命令。
- 実行: (1+(1−ML))サイクル
- 状態: 変化しない。
neg (negate sign)
- 書式: neg Rd
- 動作: Rd’=−Rd(=!Rd+1)
- 汎用レジスタRdの値を符号反転(2の補数表現)して、Rdに書き戻す。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=!Rd’[16]
- V=Rd[15]×Rd’[15]
- Z=(Rd’=0)
nop (no operation)
- 書式: nop
- 動作: なし
- 実行: 1サイクル
- 状態: 変化しない。
not (bitwise not)
- 書式: not Rd
- 動作: Rd’=!Rd
- 汎用レジスタRdの値をビット毎論理NOT演算して、Rdに書き戻す。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=0
- V=0
- Z=(Rd’=0)
or (bitwise or)
- 書式: or Rd,Rs
- 動作: Rd’=Rd|Rs
- 汎用レジスタRd,Rsをビット毎論理OR演算して、Rdに書き戻す。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=0
- V=0
- Z=(Rd’=0)
ori (bitwise or immediate)
- 書式: ori Rd,imm8
- Rdは汎用レジスタ(r0〜r7)。imm8は符号無8ビット即値。
- 動作: Rd’=Rd|uint8(imm8)
- 汎用レジスタRdと即値imm8(8ビット符号無整数)をビット毎論理OR演算して、Rdに書き戻す。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=0
- V=0
- Z=(Rd’=0)
pause (pause until interrupt request coming)
- 書式: pause
- 動作: while (!IRQ) ;
- 割り込み要求が来るまで一時停止する。
- 割り込み要求が来ると、
- 状態レジスタsrのIE[1:0]>割り込みレベルだった場合には、割り込み処理を開始する。
- 状態レジスタsrのIE[1:0]≦割り込みレベルだった場合には、次の命令を実行する。
- CPUに対する割り込み要求以外の条件では、pause命令から抜けられない。
- 実行: 1サイクル以上
- 状態: 変化しない
popcw (pop control register word from stack)
- 書式: popcw Rc
- 動作: Rc=uint16([Sp++])
- 制御レジスタRcをスタックから取り出す。
- 別名popcも使用可能。
- 実行: 2サイクル
- 状態: 変化しない。
- ただし、Rcが状態レジスタsrの場合は、スタックから取り出した値が状態フラグ(N,C,V,Z)にセットされる。
popw (pop register word from stack)
- 書式: popw Rd
- Rdは汎用レジスタ(r0〜r7)。
- 別名popも使用可能。
- 動作: Rd=uint16([Sp++])
- 実行: 2サイクル
- 状態: 変化しない。
pushcw (push control register word on stack)
- 書式: pushcw Rc
- 動作: [--Sp]=uint16(Rc)
- 制御レジスタRcをスタックへ積む。
- 別名pushcも使用可能。
- 実行: 1サイクル
- 状態: 変化しない。
pushw (push register word on stack)
- 書式: pushw Rs
- Rsは汎用レジスタ(r0〜r7)。
- 別名pushも使用可能。
- 動作: [--Sp]=uint16(Rs)
- 実行: 1サイクル
- 状態: 変化しない。
rti (return from interrupt)
- 書式: rti
- 動作: Sr=uint16([Sp++]); Pc=uint16([Sp++])
- スタックから、状態レジスタsr→プログラムカウンタpcの順で取り出す。
- 本命令の次命令は実行されず、スタックから取り出した新しいPcの指し示すアドレスから命令をフェッチして実行する。
- 実行: 4サイクル
- 状態: 変化しない
- ただし、スタックから取り出した値が状態フラグ(N,C,V,Z)にセットされる。
rtnw (return from jalw)
- 書式: rtnw
- 動作: Pc=uint16([Sp++])
- プログラムカウンタpcをスタックから取り出す。
- 本命令の次命令は実行されず、スタックから取り出した新しいPcの指し示すアドレスから命令をフェッチして実行する。
- 別名rtnも使用可能。
- 実行: 3サイクル
- 状態: 変化しない。
sbb (subtract with borrow)
- 書式: sbb Rd,Rs
- 動作: Rd’=Rd−Rs−Sr[C]
- 2つのレジスタ値と状態レジスタsrのCフラグ値を減算して、Rdに書き戻す。
- 複数レジスタ減算実行時のゼロ判定が可能な様に、直前のSr[Z]フラグ値を継承する。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=!Rd’[16]
- V=Rd[15]×(!Rs[15])×(!Rd’[15])+(!Rd[15])×Rs[15]×Rd’[15]
- Z=(Rd’=0)×Sr[Z]
sbbz (subtract zero with borrow)
- 書式: sbbz Rd
- 動作: Rd’=Rd−0−Sr[C]
- レジスタ値と状態レジスタsrのCフラグ値を減算して、Rdに書き戻す。
- 複数レジスタ減算実行時のゼロ判定が可能な様に、直前のSr[Z]フラグ値を継承する。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=!Rd’[16]
- V=Rd[15]×(!Rd’[15])
- Z=(Rd’=0)×Sr[Z]
sesrh (set sr high byte's bit)
- 書式: sesrh imm3
- 動作: Sr[8+imm3]=1
- 状態レジスタsrの第(8+imm3)ビットを1にセットする。
- 実行: 1サイクル
- 状態: 変化しない
sesrl (set sr low byte's bit)
- 書式: sesrl imm3
- 動作: Sr[imm3]=1
- 状態レジスタsrの第imm3ビットを1にセットする。
- 実行: 1サイクル
- 状態: 変化しない
- ただし、imm3が演算フラグを指す場合は、そのフラグがセットされる。
stb (store data byte)
- 書式: stb [Rd],Rs
- 動作: [Rd]=uint8(Rs[7:0])
- 汎用レジスタRdの指し示すアドレスへ8ビットバイトデータを書き込む。
- 書き込むデータは汎用レジスタRsの下位8ビット。
- 実行: 1サイクル
- 状態: 変化しない。
stbx (store data byte extended address)
- 書式: stbx [Tr:Rd],Rs
- Rd,Rsは汎用レジスタ(r0〜r7)。Trは一時レジスタ。
- 動作: [Tr:Rd]=uint8(Rs[7:0])
- 一時レジスタtrを上位16ビット、汎用レジスタRdを下位16ビットとする32ビット拡張アドレスへ8ビットバイトデータを書き込む。
- 書き込むデータは汎用レジスタRsの下位8ビット。
- 実行: Nサイクル
- 状態: 変化しない。
stw (store data word)
- 書式: stw [Rd],Rs
- 動作: [Rd]=uint16(Rs)
- 汎用レジスタRdの指し示すアドレスへ16ビットワードデータを書き込む。
- Rdが奇数アドレスであってはならない。
- 実行: 1サイクル
- 状態: 変化しない。
stwsp (store data word sp relative)
- 書式: stwsp [Sp+Rn],Rs
- Rn,Rsは汎用レジスタ(r0〜r7)。Spはスタックポインタ。
- 別名stspも使用可能。
- 動作: Tr=Sp+Rn; [Tr]=uint16(Rs)
- スタックポインタspに汎用レジスタRnを加算したアドレスへ、16ビットワードデータを書き込む。
- Sp+Rnが奇数アドレスであってはならない。
- 一時レジスタtrを使用してデータを破壊する。
- 実行: 2サイクル
- 状態: 変化しない
stwx (store data word extended address)
- 書式: stwx [Tr:Rd],Rs
- Rd,Rsは汎用レジスタ(r0〜r7)。Trは一時レジスタ。
- 動作: [Tr:Rd]=uint16(Rs)
- 一時レジスタtrを上位16ビット、汎用レジスタRdを下位16ビットとする32ビット拡張アドレスへ16ビットワードデータを書き込む。
- Rdが奇数アドレスであってはならない。
- 実行: Nサイクル
- 状態: 変化しない。
sub (subtract)
- 書式: sub Rd,Rs
- 動作: Rd’=Rd−Rs
- 汎用レジスタRdからRsを減算して、Rdに書き戻す。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=!Rd’[16]
- V=Rd[15]×(!Rs[15])×(!Rd’[15])+(!Rd[15])×Rs[15]×Rd’[15]
- Z=(Rd’=0)
subi (subtract immediate)
- 書式: subi Rd,imm8
- Rdは汎用レジスタ(r0〜r7)。imm8は符号無8ビット即値。
- 動作: Rd’=Rd−uint8(imm8)
- 汎用レジスタRdから即値imm8(8ビット符号無整数)を減算して、Rdに書き戻す。
- 実行: 1サイクル
- 状態:
- N=Rd’[15]
- C=!Rd’[16]
- V=Rd[15]×(!Rd’[15])
- Z=(Rd’=0)
アセンブラ
アセンブラの入手方法、文法などについて記載されたマニュアルはこちらをご参照ください。
改訂履歴