公開日:2026/04/11
38th Season
#38-9 週刊「スタックマシンを作る」付録
このページは、本HPで作成したオリジナル極小CPUコアSamariumの命令セットマニュアルです。
詳細については、以下リンクから本文を参照してください。
本文へ戻る。
Samarium Instruction Set Manual
Samarium CPUコア概要
Samariumは、極小の16ビットCPUコアです。ハーバードアーキテクチャを採用したスタックマシンであり、命令コードを8ビットフェッチバスから読み込んで実行します。16ビットのメモリバスを通して、CPU外部のRAMやI/Oユニット(メモリマップドI/O)などのリソースにアクセスすることが出来ます。
フェッチバス、メモリバス共、16ビットアドレスを持っており、従ってメモリ空間は最大64Kバイトです。
Samariumは8ビットの命令コードを持ったスタックマシンです。
Samariumと言う名称は、スタックマシン(Stack Machine)の頭文字Smを元素記号とするサマリウムに由来します。サマリウムは、原子番号62、希土類元素、ランタノイド、放射性物質、α崩壊でNd(Neodymium)になる、等の特長を持っています。
スタックポインタsp並びにプログラムカウンタpcはリセット信号で0x0000に初期化されるので、Samariumリセット解除後、常に0x0000番地の命令から実行を開始します。
- 凡例:
- IMM7: 即値。7ビット符号無整数。
- EIMM5: 符号化即値。5ビット符号無整数。
- EIMM5を復号化した16ビット整数値をEIMM5’と記す場合がある。
- 動作:
- 「動作:」記述中の演算子(!,×,÷)は、各々、ビット毎論理NOT、算術乗算、除算演算子を表す。
- 右シフト演算子(>>>)は、符号無右シフトを表す。
- その他の演算子はC言語などと同じ。
- 状態: 命令実行前/後のスタック状態変化。
割り込み
CPU最上位のIRQ信号がアサートされると、割り込みを受け付けることができます。
CPU内部に割り込みベクタivと、割り込み許可IEビットを持っています。
CPUのリセット解除後、Iv=0x0000、IE=0で初期化されていて、割り込みが禁止された状態なので、IRQがアサートされても、CPUが割り込みを受け付ける事はありません。
ijal命令(別名setiv命令)を実行して、有効な割り込みサービスルーチン(ISR;Interrupt Service Routine)のエントリアドレスを設定すると、同時にIEビット=1となって、割り込みを受け付け可能な状態となります(※)。
この状態の時にIRQがアサートされると、現在実行中の次の命令をフェッチするタイミングで割り込みが受け付けられ、ISRに制御が移ります。ISRへ分岐する時、フェッチ中だった次命令のアドレスがスタックへ積まれ、更にIEビット=0にクリアされて多重割り込みが禁止されます。
※ijal命令は、いかにも分岐しそうな名前ですが、実行しても直ちに分岐する事はありません。別名setiv命令が示す通り、割り込みベクタivにISRのエントリアドレスを設定する命令です。IRQ信号がアサートされるとISRへ分岐します。
ISR内で割り込み処理の実行が終わったら、ijmp命令(別名rti命令)を実行すると、IEビット=1にセットしてから、スタックに退避されていた復帰先アドレスへ復帰します(※)。
一時的に割り込みを禁止したい場合、ijal命令でIv=0x0000を設定すると、同時にIEビット=0へ設定されます。
※単なるjmp命令(別名rtn命令)では、IEビットをセットしないので、割り込みが禁止されたままとなる事に注意してください。ISRからの復帰にはijmp命令(別名rti命令)が適しています。
命令コード
全命令は、スタックから取り出す(pop)データ数と、オペランドの種類(符号化即値または即値)によって分類して、以下表の様な命令コードを割り当てています。
| bit7 |
bit6 |
bit5 |
bit4 |
bit3 |
bit2 |
bit1 |
bit0 |
Instruction |
| 0 |
0 |
0 |
INST_0 |
other N pop instruction |
| 0 |
0 |
1 |
INST_1 |
1 pop instruction |
| 0 |
1 |
0 |
INST_2 |
2 pop instruction |
| 0 |
1 |
1 |
EIMM5 |
Encoded immediate instruction |
| 1 |
IMM7 |
Immediate instruction |
次節と合わせてご確認ください。
命令セット一覧
以下に命令セットの形式順で一覧表を示します。
| No. |
Inst |
b[7] |
b[6:5] |
b[4:0] |
Code |
Description |
Operation |
| 1 |
nop |
0 |
0 |
0 |
00 |
no operation |
none |
| 2 |
pause |
0 |
0 |
1 |
01 |
pause |
pause until IRQ=1 |
| 3 |
copr |
0 |
0 |
2 |
02 |
co-processor call |
pop ccmd; pop Stk1; pop Stk2; push Stk2<ccmd>Stk1 |
| 4 |
not |
0 |
1 |
0 |
20 |
bit wise not |
pop Stk1; push ~Stk1 |
| 5 |
cend |
0 |
1 |
1 |
21 |
convert endian |
pop Stk1; push (Stk1<<8)+(Stk1>>>8) |
| 6 |
lsl |
0 |
1 |
2 |
22 |
logical shift left |
pop Stk1; push Stk1<<1 |
| 7 |
lsr |
0 |
1 |
3 |
23 |
logical shift right |
pop Stk1; push Stk1>>>1 |
| 8 |
asr |
0 |
1 |
4 |
24 |
arithmetic shift right |
pop Stk1; push Stk1>>1 |
| 9 |
neg |
0 |
1 |
5 |
25 |
negate sign |
pop Stk1; push -Stk1 |
| 10 |
jal |
0 |
1 |
20 |
34 |
jump and link |
pop Stk1; push PRG_CNT; jump to Stk1 |
| 11 |
jmp |
0 |
1 |
21 |
35 |
jump |
pop Stk1; jump to Stk1 |
| 12 |
ijal |
0 |
1 |
22 |
36 |
jump and link on interrupt |
pop Stk1; Iv=Stk1 |
| 13 |
ijmp |
0 |
1 |
23 |
37 |
jump and interrupt enable |
pop Stk1; IE=1; jump to Stk1 |
| 14 |
ldb |
0 |
1 |
24 |
39 |
load byte memory |
pop Stk1; push [read byte from Stk1] |
| 15 |
ldw |
0 |
1 |
25 |
38 |
load word memory |
pop Stk1; push [read word from Stk1] |
| 16 |
dupl |
0 |
1 |
28 |
3c |
duplicate |
pop Stk1; push Stk1; push Stk1 |
| 17 |
pop |
0 |
1 |
29 |
3d |
pop and discard |
pop Stk1 |
| 18 |
and |
0 |
2 |
0 |
40 |
bit wise and |
pop Stk1; pop Stk2; push Stk2&Stk1 |
| 19 |
or |
0 |
2 |
1 |
41 |
bit wise or |
pop Stk1; pop Stk2; push Stk2|Stk1 |
| 20 |
eor |
0 |
2 |
2 |
42 |
bit wise exclusive or |
pop Stk1; pop Stk2; push Stk2^Stk1 |
| 21 |
add |
0 |
2 |
3 |
43 |
add |
pop Stk1; pop Stk2; push Stk2+Stk1 |
| 22 |
sub |
0 |
2 |
4 |
44 |
subtract |
pop Stk1; pop Stk2; push Stk2-Stk1 |
| 23 |
cmp |
0 |
2 |
5 |
45 |
compare |
pop Stk1; pop Stk2; push NCVZS(Stk2-Stk1) |
| 24 |
cjmp |
0 |
2 |
20 |
54 |
conditional jump |
pop Stk1; pop Stk2; jump to Stk1 if Stk2 |
| 25 |
njmp |
0 |
2 |
21 |
55 |
negative conditional jump |
pop Stk1; pop Stk2; jump to Stk1 if !Stk2 |
| 26 |
stb |
0 |
2 |
24 |
59 |
store byte memory |
pop Stk1; pop Stk2; [write byte to Stk1]=Stk2 |
| 27 |
stw |
0 |
2 |
25 |
58 |
store word memory |
pop Stk1; pop Stk2; [write word to Stk1]=Stk2 |
| 28 |
swap |
0 |
2 |
28 |
5c |
swap |
pop Stk1; pop Stk2; push Stk1; push Stk2 |
| 29 |
psei |
0 |
3 |
EIMM5 |
60 |
push encoded immediate |
push EIMM5 |
| 30 |
sldi |
1 |
IMM7 |
80 |
shift and load immediate |
pop Stk1; push (Stk1<<7)+IMM7 |
命令セット
以下に、全30命令を処理内容別に分類しておきます。
※丸カッコ()内は、命令コードが等しい別名です。
以降、各命令をアルファベット昇順で説明します。
add (add)
- 書式: add
- 動作: pop Stk1; pop Stk2; push Stk2+Stk1
- スタックから2数を取り出して、加算してスタックへ積む。
- 実行: 2サイクル
- 状態:
and (bit wise and)
- 書式: and
- 動作: pop Stk1; pop Stk2; push Stk2&Stk1
- スタックから2数を取り出して、ビット毎AND演算してスタックへ積む。
- 実行: 2サイクル
- 状態:
asl (arithmetical shift left)
asr (arithmetical shift right)
- 書式: asr
- 動作: pop Stk1; push Stk1>>1
- スタックから取り出した値を、1ビット符号付右シフトしてスタックへ積む。
- 実行: 1サイクル
- 状態:
cend (convert endian)
- 書式: cend
- 動作: pop Stk1; push (Stk1<<8)+(Stk1>>>8)
- スタックから取り出した値を、エンディアン変換(BE⇔LE)してスタックへ積む。
- 実行: 1サイクル
- 状態:
cjmp (conditional jump)
- 書式: cjmp
- 動作: pop Stk1; pop Stk2; jump to Stk1 if Stk2
- スタックからアドレスと条件値を取り出して、条件値≠0の時、分岐する。
- 条件値=0の場合は、次の命令に制御が移る。
- 実行: 2/3サイクル
- 状態:
-
-
Cond≠0の時、Addrへ分岐する。
- Cond=0なら、次命令へ制御が移る。
cmp (compare)
- 書式: cmp
- 動作: pop Stk1; pop Stk2; push NCVZS(Stk2-Stk1)
- スタックから2数を取り出して、減算し、演算フラグ(NCVZS)をスタックへ積む。
- 演算フラグのセット条件は、Stk’=Stk2−Stk1として、以下の通り。
- N=Stk’[15]
- C=!Stk’[16]
- V=Stk1[15]×(!Stk2[15])×(!Stk’[15])+(!Stk1[15])×Stk2[15]×Stk’[15]
- Z=( Stk’=0 )
- S=N^V
- ※上式で、演算子(×)はビット毎論理積AND、演算子(+)はビット毎論理和OR、演算子(^)はビット毎排他的論理和EORを表す。
- 演算フラグ(NCVZS)は最下位5ビット配置、上位11ビットは常にゼロ。
- つまり、スタックへ積まれる値は2進数で、0b0000_0000_000N_CVZS。
- 実行: 2サイクル
- 状態:
copr (co-processor call)
- 書式: copr
- 動作: pop ccmd; pop Stk1; pop Stk2; push Stk2<ccmd>Stk1
- スタックから3数を取り出して、外部コプロセッサへコマンドを発行、演算結果をスタックへ積む。
- こちらのコプロセッサ疑似命令も参照。
- 実行: 3+Nサイクル
- 状態:
-
| ccmd |
→ |
|
| B |
|
| A |
A
<ccmd>
B
|
| copr |
dupl (duplicate)
- 書式: dupl
- 動作: pop Stk1; push Stk1; push Stk1
- スタックから取り出した値を、2個に複製してスタックへ積む。
- 実行: 2サイクル
- 状態:
eor (bit wise exclusive or)
- 書式: eor
- 動作: pop Stk1; pop Stk2; push Stk2^Stk1
- スタックから2数を取り出して、ビット毎EOR演算してスタックへ積む。
- 実行: 2サイクル
- 状態:
ijal (jump and link on interrupt)
- 書式: ijal
- 動作: pop Stk1; Iv=Stk1; IE=( Iv!=0 )
- スタックからアドレスを取り出して、割り込みベクタivを設定する。
- 割り込みサービスルーチンのアドレスをIvに設定する命令。
- 同時に割り込み許可IEビット=( Iv≠0 )を設定する。
- 割り込みを受け付けると、Ivに設定したアドレスに分岐する。
- ※本命令を実行しても直ちに分岐する事はない。割り込みを受け付けた時に分岐する。
- 実行: 1サイクル
- 状態:
-
-
割り込みベクタiv=Addrを設定する。
- IEビット=( Iv≠0 )を設定する(割り込み許可)。
ijmp (jump and interrupt enable)
- 書式: ijmp
- 動作: pop Stk1; IE=1; jump to Stk1
- スタックからアドレスを取り出して、割り込み許可IEビット=1とした後、分岐する。
- ただしIv=0x0000の場合は、本命令を実行しても常にIEビット=0である事に留意。
- 割り込みサービスルーチン(ISR)からの復帰命令。
- 実行: 2サイクル
- 状態:
-
-
Addrへ分岐する。
- IEビット=( Iv≠0 )を設定する(割り込み許可)。
jal (jump and link)
- 書式: jal
- 動作: pop Stk1; push PRG_CNT; jump to Stk1
- スタックからアドレスを取り出して、プログラムカウンタをスタックへ積んだ後、分岐する。
- 実行: 2サイクル
- 状態:
jmp (jump)
- 書式: jmp
- 動作: pop Stk1; jump to Stk1
- 実行: 2サイクル
- 状態:
ldb (load byte memory)
- 書式: ldb
- 動作: pop Stk1; push [read byte from Stk1]
- スタックからアドレスを取り出して、アドレスから読み出した8ビット符号無データをスタックへ積む。
- 実行: (1+N)サイクル
- 状態:
ldw (load word memory)
- 書式: ldw
- 動作: pop Stk1; push [read word from Stk1]
- スタックからアドレスを取り出して、アドレスから読み出した16ビットデータをスタックへ積む。
- 実行: (1+N)サイクル
- 状態:
lsl (logical shift left)
- 書式: lsl
- 動作: pop Stk1; push Stk1<<1
- スタックから取り出した値を、1ビット左シフトしてスタックへ積む。
- 実行: 1サイクル
- 状態:
lsr (logical shift right)
- 書式: lsr
- 動作: pop Stk1; push Stk1>>>1
- スタックから取り出した値を、1ビット符号無右シフトしてスタックへ積む。
- 実行: 1サイクル
- 状態:
neg (negate sign)
- 書式: neg
- 動作: pop Stk1; push -Stk1
- スタックから取り出した値を、符号反転してスタックへ積む。
- 実行: 2サイクル
- 状態:
njmp (negative conditional jump)
- 書式: njmp
- 動作: pop Stk1; pop Stk2; jump to Stk1 if !Stk2
- スタックからアドレスと条件値を取り出して、条件値=0の時、分岐する。
- 条件値≠0の場合は、次の命令に制御が移る。
- 実行: 2/3サイクル
- 状態:
-
-
Cond=0の時、Addrへ分岐する。
- Cond≠0なら、次命令へ制御が移る。
nop (no operation)
- 書式: nop
- 動作: なし
- 実行: 1サイクル
- 状態:
not (bitwise not)
- 書式: not
- 動作: pop Stk1; push ~Stk1
- スタックから取り出した値を、ビット毎論理NOT演算してスタックへ積む。
- 実行: 1サイクル
- 状態:
or (bit wise or)
- 書式: or
- 動作: pop Stk1; pop Stk2; push Stk2|Stk1
- スタックから2数を取り出して、ビット毎OR演算してスタックへ積む。
- 実行: 2サイクル
- 状態:
pause (pause)
- 書式: pause
- 動作: pause until IRQ=1
- 割り込み要求が発生(IRQ=1)するまで一時停止して待機する。
- IRQ=1となった時、
- 割り込み許可IEビット=1なら、割り込みを受け付けてISRへ分岐する。
- 割り込み許可IEビット=0なら、次命令へ制御が移る。
- 実行: (1+N)サイクル
- 状態:
pop (pop and discard)
- 書式: pop
- 動作: pop Stk1
- 実行: 1サイクル
- 状態:
psei (push encoded immediate)
- 書式: psei EIMM5
- 動作: push EIMM5’
- 5ビット符号化即値EIMM5(以下表参照)を、復号化EIMM5’してスタックへ積む。
-
符号化即値
EIMM5
|
16ビット値
(復号化)
|
組み込みラベル名等 |
| 0x00 |
0 |
MIN_UINT,ZERO |
| 0x01 |
1 |
- |
| 0x02 |
2 |
- |
| 0x03 |
3 |
- |
| 0x10 |
0xffff |
MAX_UINT,MINUS1 |
| 0x11 |
0x7fff |
MAX_INT |
| 0x12 |
0x8000 |
MIN_INT,SGN_BIT,WORD_SG |
| 0x13 |
0x00ff |
BYTE_LO |
| 0x14 |
0x0080 |
BYTE_SG |
| 0x18 |
0x0620 |
CORE_ID |
| 0x19 |
Stack Size |
STK_SIZ |
| 0x1a |
Sp |
STK_PTR |
| 0x1b |
Pc |
PRG_CNT |
| 0x1c |
Iv |
INT_VEC |
| 0x1d |
CPU Status |
CPU_STS |
- ※上表に無いコードは未割り当てであり、予約済み。指定禁止。
- CORE_ID:
- SamariumコアのID番号をスタックへ積む。
- 将来、CPU種を判定するための予約機能。
- 現時点では、元素Sm(サマリウム)の原子番号62を表す0x0620(BCD)をスタックへ積む。
- STK_SIZ:
- 現在実行中のSamariumコアに内蔵されたスタックのサイズ(段数)をスタックへ積む。
- サイズ(段数)は実装依存。
- STK_PTR:
- 実行時点のスタックポインタsp値をスタックへ積む。
- 実行後、スタックへ積んだことでSp=Sp+1となる事に留意。
- PRG_CNT:
- 現在のプログラムカウンタpc値をスタックへ積む。
- 「psei PRG_CNT」の命令コード格納アドレス+1がスタックへ積まれる。
- INT_VEC:
- CPU_STS:
- Samariumの最上位モジュールインターフェイスに存在するcpu_sts[15:0]信号に接続した値をスタックへ積む。
- 従って、スタックへ積まれる値は実装依存。
- 実行: 1サイクル
- 状態:
rti (return from interrupt)
rtn (return from subroutine)
setiv (set interrupt vector)
setpc (set program counter)
sldi (shift and load immediate)
- 書式: sldi IMM7
- 動作: pop Stk1; push (Stk1<<7)+IMM7
- スタックから取り出した値に、7ビット即値IMM7を7ビット左シフト入力して、スタックへ積む。
- 実行: 1サイクル
- 状態:
stb (store byte memory)
- 書式: stb
- 動作: pop Stk1; pop Stk2; [write byte to Stk1]=Stk2
- スタックからアドレスとデータを取り出して、アドレスへ8ビットデータを書き込む。
- データの下位8ビットが有効。
- 実行: (1+N)サイクル
- 状態:
-
-
メモリ空間のアドレスAddrへバイトデータWrite_Bを書き込む。
stw (store word memory)
- 書式: stw
- 動作: pop Stk1; pop Stk2; [write word to Stk1]=Stk2
- スタックからアドレスとデータを取り出して、アドレスへ16ビットデータを書き込む。
- アドレスはワード境界に乗っていなくてはならない。
- 実行: (1+N)サイクル
- 状態:
-
-
メモリ空間のアドレスAddrへワードデータWrite_Wを書き込む。
sub (subtract)
- 書式: sub
- 動作: pop Stk1; pop Stk2; push Stk2-Stk1
- スタックから2数を取り出して、減算してスタックへ積む。
- 実行: 2サイクル
- 状態:
swap (swap)
- 書式: swap
- 動作: pop Stk1; pop Stk2; push Stk1; push Stk2
- スタックから2数を取り出して、逆順にスタックへ積む。
- 実行: 3サイクル
- 状態:
アセンブラ
SamariumアセンブラはOlive+のスクリプトで提供します。以下にリンクします。
アセンブラスクリプト:asm_sama.olv
※スクリプト(.olv)を実行するには拙作Olive+をWindowsにインストールしてください。
アセンブラ文法
- ソースファイル: アセンブラ行,……
- アセンブラ行: 命令語 引数リスト 注釈 <改行コード>
- 命令語、引数リスト、注釈は、空白で区切られる。
- 空白: 半角スペース(0x20)または、タブコード(0x09)
- 「//」または「#」から行末までは注釈として無視される。
- 命令語、引数リスト、注釈は省略可能。
- ただし、命令語を省略して引数リストだけを指定する事は禁止。
- 命令語: 命令/疑似命令/アドレスラベル:/アドレスラベル*
- 命令: CPU命令の何れか。
- アドレスラベル:: アドレスラベルの定義。
- 語尾にコロン(:)。
- 引数としてアドレスラベルを参照する場合、定数式を使う事は禁止。
- アドレスラベル*: アドレスラベルのサブルーチン呼び出し。
- 語尾にアスタリスク(*)。
- 「jal アドレスラベル」に展開される。
- 引数リスト: 引数,……
- カンマ(,)で区切って、1個〜複数個指定可能。
- 区切り文字カンマ(,)が連続する、空の引数は指定禁止。
- 引数並びに引数リストに、空白を含むことはできない。
- 左から右へ指定された順に、値がスタックへ積まれる。
- 命令語は、引数リストをスタックへ積んだ後で、実行される。
- 引数: 直接値/間接値/浮動小数値
- 直接値: 定数値/定数式/定数ラベル/アドレスラベル
- 定数値や定数式等はOlive+が評価するので、Olive+のスクリプト言語仕様に準ずる。
- 「push 直接値」に展開される。
- 定数式にアドレスラベルを参照することはできない。
- 間接値: [直接値]
- 角括弧[ ]で括られた直接値をアドレスと見なし、アドレスから読み出した16ビットデータをスタックへ積む。
- 「ldw 直接値」に展開される。
- 浮動小数値: half[浮動小数]
- 角括弧[ ]で括られた半精度浮動小数のバイナリ値をスタックへ積む。
- 「push 浮動小数バイナリ値」に展開される。
- 例)push half[1.3125]
- 1.3125の半精度浮動小数バイナリ値は0x3d40なので、0x3d40がスタックへ積まれる。
- 「push 0x3d40」と同義。
- 注釈: //注釈文字列/#注釈文字列
- 「//」または「#」から行末までは注釈として無視される。
- 疑似命令: アセンブラを制御する疑似命令。
- asm "filename.ext"
- アセンブル結果をファイル"filename.ext"へ出力する。
- 省略すると、"asm_sama.v"が推定される。
- 拡張子.extによって、出力ファイル形式が異なる。
- ".v": Verilog-HDLの組み合わせ論理ROM形式(RTL)で出力。
- ".mem": Verilog-HDLの$readmemh()形式で出力。
- align <size>
- アドレスが<size>境界に乗るように調整する。
- 調整のため、nop命令コード(0x00)が挿入される場合がある。
- dats "string"
- 文字列"string"をプログラムコード中に展開する。
- 文字列には、ASCII文字、S-JIS文字を使用可能。
- 以下のエスケープシーケンスが使用可能。
- '\\': バックスラッシュ(\)
- '\"': ダブルクオート(")
- '\0': NILコード、0x00
- '\r': 復帰コードCR、0x0d
- '\n': 改行コードLF、0x0a
- '\t': タブコード、0x09
- '\x<hex2>': 8ビットバイナリコード、0x<hex2>
- dats疑似命令の文字列は、datw疑似命令に展開される。
- 文字列が奇数バイトだった場合、文字列の最後に1バイトの0x00データが追加され、偶数バイトに調整される。
- 丁度偶数バイトだった場合は、何も追加されない。
- エスケープシーケンスで明示的に指定しない限り、文字列データの終端にNIL('\0')コードが挿入される保証は無い事に注意。
- datw <value>[,<value2>,……]
- 16ビットワードデータ<value>をプログラムコード中に展開する。
- データが16ビットワード境界に乗る事は保証されない。
- equ <label>,<value>
- 定数ラベル<label>に定数<value>を割り当てる。
- 既に定義した定数ラベル<label>への再定義が可能。
- 定数ラベル<label>を定義した時点から後方のequ疑似命令による参照で、新しい値<value>が有効。
- その他命令/疑似命令からの参照では、最後のequ疑似命令で定義された値が有効。
- push <value>
- 定数<value>をスタックへ積む。
- 定数<value>値によって、最適な1命令〜3命令に展開される。
- pushf <value>
- 定数<value>をスタックへ積む。
- 必ず、「psei,sldi,sldi」の3命令に展開する。
- コプロセッサ疑似命令: CPU外部に接続されるコプロセッサを制御する疑似命令。
- 現在Samariumに接続可能なコプロセッサは以下の通り。
- 各コプロセッサ疑似命令は、対象のコプロセッサに対するコプロセッサコマンドccmdに応じて、copr命令に展開される。
- Moscovium用のコプロセッサをそのまま流用している事、
- 全てcopr命令によって制御される事、
- 等によって、引数や、スタックへ積まれる演算結果に制約が生じる事に注意。
- 全てのコプロセッサ疑似命令は、2個の引数を必要とする。
- 引数が必要ない場合や、1個で十分な場合でも、必ず2個の引数をスタックへ積む必要がある。
- 必要に応じてダミーデータをスタックへ積んでからコプロセッサ疑似命令を実行する事。
- 接続されていないコプロセッサの命令を実行すると、常に0がスタックへ積まれる。
- なお、未定義のccmdを実行する事は禁止。実行した場合、スタックへ積まれる値は保証しない。
- MULC16:
- mulu: 16ビット符号無乗算(ccmd=0x01)
- 「mulu A,B」に対して、積A×Bの下位16ビットがスタックへ積まれる。
- muls: 16ビット符号付乗算(ccmd=0x02)
- 「muls A,B」に対して、積A×Bの下位16ビットがスタックへ積まれる。
- mulh: 積の上位16ビットの取得(ccmd=0x03)
- 「mulh 0,0」に対して、直前に実行した乗算A×Bの上位16ビットがスタックへ積まれる。
- 引数2個はダミーデータ(0を推奨)。
- DIVC16:
- divu: 16ビット符号無除算(ccmd=0x0e)
- 「divu A,B」に対して、商A÷Bがスタックへ積まれる。
- divs: 16ビット符号付除算(ccmd=0x0f)
- 「divs A,B」に対して、商A÷Bがスタックへ積まれる。
- divr: 剰余の取得(ccmd=0x0d)
- 「divr 0,0」に対して、直前に実行した除算の剰余A%Bがスタックへ積まれる。
- 引数2個はダミーデータ(0を推奨)。
- H-FPU:
- fadd: 浮動小数加算(ccmd=0x11)
- 「fadd A,B」に対して、A+Bがスタックへ積まれる。
- fsub: 浮動小数減算(ccmd=0x12)
- 「fsub A,B」に対して、A−Bがスタックへ積まれる。
- fmul: 浮動小数乗算(ccmd=0x13)
- 「fmul A,B」に対して、A×Bがスタックへ積まれる。
- fdiv: 浮動小数除算(ccmd=0x14)
- 「fdiv A,B」に対して、A÷Bがスタックへ積まれる。
-
fhalf: 整数→浮動小数変換(ccmd=0x16)
- 「fhalf A,0」に対して、16ビット符号無整数Aを浮動小数へ変換した値がスタックへ積まれる。
- 2個目の引数はダミーデータ(0を推奨)。
- こちらのhhalf命令も参照。
- fuint: 浮動小数→整数変換(ccmd=0x17)
- 「fuint A,0」に対して、浮動小数Aの絶対値を16ビット符号無整数へ変換した値がスタックへ積まれる。
- 2個目の引数はダミーデータ(0を推奨)。
- こちらのhuint命令も参照。
- fmvsg: 浮動小数符号転送(ccmd=0x19)
- 「fmvsg A,B」に対して、Bの符号をAの符号へ転送したA×sgn (A)×sgn (B)がスタックへ積まれる。
- ここでsgn (x)=(x<0)?−1:(x>0)?1:0。
- fcmp: 浮動小数比較(ccmd=0x1b)
- 「fcmp A,B」に対して、A−Bを実行した結果の演算フラグNCVZがスタックへ積まれる。
- 演算フラグNCVZは、第7ビット〜第4ビットに割り当てられる。
- つまり、スタックへ積まれる値は2進数で、0b0000_0000_NCVZ_0000。
- 演算フラグのセット条件については、こちらのhcmp命令を参照。
- ftrunc: 小数点以下切り捨て(ccmd=0x1c)
- 「ftrunc A,0」に対して、浮動小数Aの小数点以下をゼロ方向の整数へ切り捨てた値がスタックへ積まれる。
- 小数点以下を切り捨てるだけで、浮動小数のままである事に留意。整数ではない。
- 2個目の引数はダミーデータ(0を推奨)。
- 例)円周(2π×R)を求める
- fmul half[2*3.14],[rad]
- アセンブラによって、以下の命令へ展開される。
- copr half[2*3.14],[rad],0x13
-
push half[2*3.14]
ldw rad
push 0x13
copr
- 0x13は、fmul疑似命令のコプロセッサコマンドccmd番号。
-
| |
→ |
|
→ |
0x13 |
→ |
|
| |
[rad] |
[rad] |
|
| 2×3.14 |
2×3.14 |
2×3.14 |
2×3.14
×[rad]
|
| push |
ldw |
push |
copr |
- ※各命令実行後のスタック状態を図示した。
- 例)除算(商と剰余を取得)
-
divu 14,6
divr 0,0 // 剰余(%)を取得
- アセンブラによって、以下の命令へ展開される。
-
copr 14,6,0x0e
copr 0,0,0x0d
- 0x0e/0x0dは、それぞれdivu/divr疑似命令のコプロセッサコマンドccmd番号。
- divu疑似命令によって、普通に商がスタックへ積まれる。
- 剰余を取得するためには、ダミーの引数2個を渡して、divr疑似命令を実行すれば良い。
- divr疑似命令は、直前に実行した除算の剰余をスタックへ積む。
-
| |
→ |
|
| |
14%6 |
| 14÷6 |
14÷6 |
| divu |
divr |
- ※「%」は剰余演算子。
具体的な例等を交えた解説は、こちらから本文を参照してください。
改訂履歴
| 日付 |
項目 |
備考 |
| 2026/04/11 |
Samarium命令セットマニュアル |
作成。 |

