『 RETOROF-16KのISA(命令一覧)』  Copyright © 2015 GATARO All Rights Reserved.    筆者のメインサイト

本ページは「とりあえず版」です

RETROF-16KのISA一覧表

RETOROF-16Kとは筆者が作成したTTL(標準ロジック)のみで作成したCPUの名前であり、それを搭載したワンボードコンピュータの名称でもあります。

この手作りCPUは機械語命令自体もオリジナルですから、当然このCPU用のコンパイラやアセンブラは自分で作らなければいけません。
セルフ(このCPUでコンパイルやアセンブルする)はまだ困難ですから、クロス(他のコンピュータでコンパイルやアセンブルし、オブジェクトコードのみを転送する)方式のコンパイラとアセンブラを作成中です。

(2015年1月現在)


ここで紹介するのは開発環境(コンパイラやアセンブラ等を含む一連のアプリ)を構築する際に、実際にビルドの対象としているインクルードファイルです。(言語はC++/CLI)
単なるインクルードファイルであり、命令一覧表として作成した資料ではありませんが、結果的にRETOROF-16Kの全機械語命令やその働き、ニモニック等、必要な情報は全てコメントとして網羅しているので、命令一覧表の代りに公開することに致しました。

実際のソースコード(インクルードファイル、R16Kcode.h)

//#################################################################################################
// RETROF-16K 統合開発環境 オブジェクトコード定義  JAN.2015 (C)GATARO RETROF PROJECT
//#################################################################################################

#define MODE 0   //アドレッシングモード
// 実際には0x0/0x100/0x200/0x300のいずれかの値をとるが、ここでは説明の便宜上全て0としている。
 


//-------------------------------------------------------------------------------------------------
// 特殊命令とフラグの変化規則
//-------------------------------------------------------------------------------------------------
//以下の3命令はフラグは実際にはLDPC命令と同様に変化するが、仕様上は実行後のフラグは不定とする
//実際のニモニックは#define値から"code"とった文字列(SFTR/ROTL/HALT)

#define codeSFTR (0x0100) // [000 XXX 01 XXXXXXXX] 右シフト 
#define codeROTL (0x0200) // [000 XXX 10 XXXXXXXX] 左ローテーション
#define codeHALT (0x0300) // [000 XXX 11 XXXXXXXX] 停止
//Xのビットは任意であるが、アセンブラ、およびコンパイラはX=0として機械語命令を生成する
#define codeMASK (0xE300) // 上記特殊命令検出用のマスクカード


// 上記3命令以外はフラグは以下の様に変化する
// Z(ゼロ)フラグは結果的にアキュムレータが0になれば経つ
// M(マイナス)フラグは結果的にアキュムレータの最上位ビットが1になれば経つ
// C(キャリー)フラグは、
//     「加算」「インクリメントロード」の場合は、結果がFFFF以上だと立ち、それ以外は落ちる
//     「減算」「デクリメントロード」 の場合は、結果が0000以下だと落ち、それ以外は立つ
//     「論理演算」および単純ロード命令の場合は不定とする 
// B(ブリンキング)は画面表示が水平帰線期間だと立つ。実行した命令の種別や結果には影響されない

//-------------------------------------------------------------------------------------------------
// プログラムカウンタ値のロード関連命令(主としてサブルーチンコール時の戻り番地保存用)
//-------------------------------------------------------------------------------------------------
//Accはアキュムレータ、Yはその命令の次の命令の格納アドレスを表すNNNNNNNNは無効(任意の値で良い)
//実際のニモニックは#define値から"code"とった文字列(DECP/INCP/SUBP/ADDP/XORP/ORP/ANDP/LDP)

#define codeDECP  (0x0000) // [000 000 00 NNNNNNNN] Y-1   -> Acc
#define codeINCP  (0x0400) // [000 001 00 NNNNNNNN] Y+1   -> Acc
#define codeSUBP  (0x0800) // [000 010 00 NNNNNNNN] Y-ACC -> Acc 【非演算子の順序が一般的CPUと逆】
#define codeADDP  (0x0C00) // [000 011 00 NNNNNNNN] ACC+Y -> Acc
#define codeXORP  (0x1000) // [000 100 00 NNNNNNNN] ACC^Y -> Acc
#define codeORP   (0x1400) // [000 101 00 NNNNNNNN] ACC|Y -> Acc
#define codeANDP  (0x1800) // [000 110 00 NNNNNNNN] ACC&Y -> Acc
#define codeLDP   (0x1C00) // [000 111 00 NNNNNNNN] Y     -> Acc

//-------------------------------------------------------------------------------------------------
// ロード/演算命令
//-------------------------------------------------------------------------------------------------
// 実際のニモニックは#define値から"code"とった文字列(DECP/INCP/SUBP/ADDP/XORP/ORP/ANDP/LDP)
// Yが意味するものは、MODE(**)の値によって変わる
//    ** = 00 の時、Yは定数値NNNNNNNNで直接指定される定数(0~255)
//                    オペランドのアセンブラ記述は、0~255 または $0~$FF(16進値で指定) 
//    ** = 01 の時、Yは定数値NNNNNNNNで指定されるレジスタ(R0~R255)が示す番地のメモリ値
//                    オペランドのアセンブラ記述は、M(R0)~M(R255)
//    ** = 10 の時、Yは定数値NNNNNNNNで指定されるレジスタ(R0~R255)の値
//                    オペランドのアセンブラ記述は、R0~R255
//    ** = 11 の時、2ワード命令となりNNNNNNNNは無効。Yは2ワード目で指定される定数(0~65535)となる
//                    オペランドのアセンブラ記述は、0~65535 または $0~$FFFF(16進値で指定)
//                    ** = 00 の時と区別が付かない場合は末尾に'L'を付ける。(ADD 1L、XOR $FFL 等)

#define codeDEC   (0x2000+MODE) // [001 000 ** NNNNNNNN] Y-1   -> Acc 【Yが定数の場合はLDと同等】
#define codeINC   (0x2400+MODE) // [001 001 ** NNNNNNNN] Y+1   -> Acc 【Yが定数の場合はLDと同等】
#define codeSUB   (0x2800+MODE) // [001 010 ** NNNNNNNN] Y-ACC -> Acc 
#define codeADD   (0x2C00+MODE) // [001 011 ** NNNNNNNN] ACC+Y -> Acc
#define codeXOR   (0x3000+MODE) // [001 100 ** NNNNNNNN] ACC^Y -> Acc
#define codeOR    (0x3400+MODE) // [001 101 ** NNNNNNNN] ACC|Y -> Acc
#define codeAND   (0x3800+MODE) // [001 110 ** NNNNNNNN] ACC&Y -> Acc
#define codeLD    (0x3C00+MODE) // [001 111 ** NNNNNNNN] Y     -> Acc

//-------------------------------------------------------------------------------------------------
// 画面ロード関係命令
//-------------------------------------------------------------------------------------------------
// 実際のニモニックは#define値から"code"とった文字列(DECV/INCV/SUBV/ADDV/XORV/ORV/ANDV/LDV)
// Yが意味するものは、MODE(**)の値によって変わる。詳細は「単純ロード/単純演算命令」と同じ。
// 但し、ロードの対象となるのは主メモリではなく画像メモリとなる。
// 画像メモリマップは左上が0番地、右上が255番地、左下が65280番地、左下が65535番地。
// 画像メモリの一つの番地は8bit構成で横に接する2画素に対応する。8bitの構成は【-RGB-RGB】。-は任意。
// ロード時はアキュムレータの上位8bitは不定となる。

#define codeDECV  (0x4000+MODE) // [010 000 ** NNNNNNNN] Y-1   -> Acc 【Yが定数の場合はLDVと同等】
#define codeINCV  (0x4400+MODE) // [010 001 ** NNNNNNNN] Y+1   -> Acc 【Yが定数の場合はLDVと同等】
#define codeSUBV  (0x4800+MODE) // [010 010 ** NNNNNNNN] Y-ACC -> Acc 
#define codeADDV  (0x4C00+MODE) // [010 011 ** NNNNNNNN] ACC+Y -> Acc
#define codeXORV  (0x5000+MODE) // [010 100 ** NNNNNNNN] ACC^Y -> Acc
#define codeORV   (0x5400+MODE) // [010 101 ** NNNNNNNN] ACC|Y -> Acc
#define codeANDV  (0x5800+MODE) // [010 110 ** NNNNNNNN] ACC&Y -> Acc
#define codeLDV   (0x5C00+MODE) // [010 111 ** NNNNNNNN] Y     -> Acc

//-------------------------------------------------------------------------------------------------
// 入力命令 (基板上の16個のスイッチの状態を読込む命令)
//-------------------------------------------------------------------------------------------------
// 実際のニモニックは#define値から"code"とった文字列(DECI/INCI/SUBI/ADDI/XORI/ORI/ANDI/LDI)
// Yが意味するものは、MODE(**)の値によって変わる。詳細は「単純ロード/単純演算命令」と同じ。
// 入力ポートは1つのみであり、ポートを指定するオペランドは無い。

#define codeDECI  (0x6000+MODE) // [011 000 ** NNNNNNNN] Y-1  -> Acc 【これは未定義命令扱いとする】
#define codeINCI  (0x6400+MODE) // [011 001 ** NNNNNNNN] Y+1  -> Acc 【これは未定義命令扱いとする】
#define codeSUBI  (0x6800+MODE) // [011 010 ** NNNNNNNN] Y-IN -> Acc 
#define codeADDI  (0x6C00+MODE) // [011 011 ** NNNNNNNN] IN+Y -> Acc
#define codeXORI  (0x6000+MODE) // [011 100 ** NNNNNNNN] IN^Y -> Acc
#define codeORI   (0x6400+MODE) // [011 101 ** NNNNNNNN] IN|Y -> Acc
#define codeANDI  (0x6800+MODE) // [011 110 ** NNNNNNNN] IN&Y -> Acc
#define codeLDI   (0x6C00+MODE) // [011 111 ** NNNNNNNN] Y    -> Acc 【これは未定義命令扱いとする】

//-------------------------------------------------------------------------------------------------
// 分岐命令
//-------------------------------------------------------------------------------------------------
// 実際のニモニックは#define値から"code"とった文字列(JMP/JPB/JNC/JC/JNZ/JZ/JNM/JM)
// 分岐先は、MODE(**)の値によって変わる
//    ** = 00 の時、CCCCCCCCNNNNNNNNの16bitで指定されるアドレス。CCCCCCCCは現在のアドレスと同じ
//                    オペランドのアセンブラ記述は、R0~R255 
//    ** = 01 の時、定数値NNNNNNNNで指定されるレジスタ(R0~R255)が示す番地のメモリ値
//                    オペランドのアセンブラ記述は、M(R0)~M(R255)
//    ** = 10 の時、定数値NNNNNNNNで指定されるレジスタ(R0~R255)が示すアドレス
//                    オペランドのアセンブラ記述は、R0~R250
//    ** = 11 の時、2ワード命令となりNNNNNNNNは無効。分岐先は2ワード目で指定される(0000~FFFF)
//                    オペランドのアセンブラ記述は、$0~$FFFF(16進値で指定)
//                    ** = 00 の時と区別が付かない場合は末尾に'L'を付ける。($FFL 等)

#define codeJMP  (0x8000+MODE) // [100 000 ** NNNNNNNN] 無条件分岐
#define codeJB   (0x8400+MODE) // [100 001 ** NNNNNNNN] ブリンク(本記述冒頭の説明参照)なら分岐
#define codeJNC  (0x8800+MODE) // [100 010 ** NNNNNNNN] キャリーフラグが立っていなければ分岐 
#define codeJC   (0x8C00+MODE) // [100 011 ** NNNNNNNN] キャリーフラグが立っていれば分岐 
#define codeJNZ  (0x9000+MODE) // [100 100 ** NNNNNNNN] ゼロフラグが立っていなければ分岐 
#define codeJZ   (0x9400+MODE) // [100 101 ** NNNNNNNN] ゼロフラグが立っていれば分岐
#define codeJNM  (0x9800+MODE) // [100 110 ** NNNNNNNN] マイナスフラグが立っていなければ分岐 
#define codeJM   (0x9C00+MODE) // [100 111 ** NNNNNNNN] マイナスフラグが立っていれば分岐

//-------------------------------------------------------------------------------------------------
// ストア命令 (分岐命令と同様の条件指定が可能)
//-------------------------------------------------------------------------------------------------
// 実際のニモニックは#define値から"code"とった文字列(ST/STB/STNC/STC/STNZ/STZ/STNM/STM)
// アキュムレータの値をレジスタまたは主メモリにストアする。ストア先は、MODE(**)の値によって変わる
//    ** = 00 の時、NNNNNNNNでで指定されるレジスタ(R0~R255)
//                    オペランドのアセンブラ記述は、R0~R255 
//    ** = 01 の時、【未定義命令扱いとする】
//                     (実際にはNNNNNNNNで指定されるレジスタが示すメモリが示すアドレスにストア)
//    ** = 10 の時、Yは定数値NNNNNNNNで指定されるレジスタ(R0~R255)の値
//                    オペランドのアセンブラ記述は、M(R0)~M(R255)
//    ** = 11 の時、2ワード命令となりNNNNNNNNは無効。ストア先は2ワード目で指定される(0000~FFFF)
//                    オペランドのアセンブラ記述は、$0~$FFFF(16進値で指定)
//                    ** = 00 の時と区別が付かない場合は末尾に'L'を付ける。($FFL 等)

#define codeST   (0xA000+MODE) // [101 000 ** NNNNNNNN] 無条件ストア
#define codeSTB  (0xA400+MODE) // [101 001 ** NNNNNNNN] ブリンク(本記述冒頭の説明参照)ならストア
#define codeSTNC (0xA800+MODE) // [101 010 ** NNNNNNNN] キャリーフラグが立っていなければストア 
#define codeSTC  (0xAC00+MODE) // [101 011 ** NNNNNNNN] キャリーフラグが立っていればストア 
#define codeSTNZ (0xB000+MODE) // [101 100 ** NNNNNNNN] ゼロフラグが立っていなければストア 
#define codeSTZ  (0xB400+MODE) // [101 101 ** NNNNNNNN] ゼロフラグが立っていればストア
#define codeSTNM (0xB800+MODE) // [101 110 ** NNNNNNNN] マイナスフラグが立っていなければストア 
#define codeSTM  (0xBC00+MODE) // [101 111 ** NNNNNNNN] マイナスフラグが立っていればストア

//-------------------------------------------------------------------------------------------------
// 画像ストア命令 (分岐命令と同様の条件指定が可能)
//-------------------------------------------------------------------------------------------------
// 実際のニモニックは#define値から"code"とった文字列(ST/SVB/SVNC/SVC/SVNZ/SVZ/SVNM/SVM)
// アキュムレータの値を画像メモリにストアする。ストア先は、MODE(**)の値によって変わる
//    ** = 00 の時、【未定義命令扱いとする】
//                    (実際にはNNNNNNNNでで指定される画像メモリにAccの値をストアする)
//    ** = 01 の時、【未定義命令扱いとする】
//                     (実際にはNNNNNNNNで指定されるレジスタが示すメモリが示すアドレスにストア)
//    ** = 10 の時、Yは定数値NNNNNNNNで指定されるレジスタ(R0~R255)が指示する場所
//                    オペランドのアセンブラ記述は、R0~R255
//    ** = 11 の時、2ワード命令となりNNNNNNNNは無効。ストア先は2ワード目で指定(0000~FFFF)
//                    オペランドのアセンブラ記述は、$0~$FFFF(16進値で指定)
//                    ** = 00 の時と区別が付かない場合は末尾に'L'を付ける。($FFL 等)

#define codeSTV  (0xC000+MODE) // [110 000 ** NNNNNNNN] 無条件ストア
#define codeSVB  (0xC400+MODE) // [110 001 ** NNNNNNNN] ブリンク(本記述冒頭の説明参照)ならストア
#define codeSVNC (0xC800+MODE) // [110 010 ** NNNNNNNN] キャリーフラグが立っていなければストア 
#define codeSVC  (0xCC00+MODE) // [110 011 ** NNNNNNNN] キャリーフラグが立っていればストア 
#define codeSVNZ (0xD000+MODE) // [110 100 ** NNNNNNNN] ゼロフラグが立っていなければストア 
#define codeSVZ  (0xD400+MODE) // [110 101 ** NNNNNNNN] ゼロフラグが立っていればストア
#define codeSVNM (0xD800+MODE) // [110 110 ** NNNNNNNN] マイナスフラグが立っていなければストア 
#define codeSVM  (0xDC00+MODE) // [110 111 ** NNNNNNNN] マイナスフラグが立っていればストア

//-------------------------------------------------------------------------------------------------
// 出力命令 (分岐命令と同様の条件指定が可能) 基板上の32個LEDに点灯/消灯を支持する命令
//-------------------------------------------------------------------------------------------------
// 実際のニモニックは#define値から"code"とった文字列(OUT/OTB/OTNC/OTC/OTNZ/OTZ/OTNM/OTM)
// 下段のLEDには常にAccの内容を表示する
// 上段のLEDに表示される値は、MODE(**)の値によって変わる
//    ** = 00 の時、定数値NNNNNNNNで直接指定される定数(0~255) 
//                    オペランドのアセンブラ記述は、0~255 または $0~$FF(16進値で指定) 
//    ** = 01 の時、定数値NNNNNNNNで指定されるレジスタ(R0~R255)が示す番地のメモリ値
//                    オペランドのアセンブラ記述は、M(R0)~M(R255)
//    ** = 10 の時、定数値NNNNNNNNで指定されるレジスタ(R0~R255)の値
//                    オペランドのアセンブラ記述は、R0~R255
//    ** = 11 の時、2ワード命令となりNNNNNNNNは無効。2ワード目で指定される値(0~65535)を表示
//                    オペランドのアセンブラ記述は、0~65535 または $0~$FFFF(16進値で指定)
//                    ** = 00 の時と区別が付かない場合は末尾に'L'を付ける。(ADD 1L、XOR $FFL 等)

#define codeOUT  (0xE000+MODE) // [111 000 ** NNNNNNNN] 無条件ストア
#define codeOTB  (0xE400+MODE) // [111 001 ** NNNNNNNN] ブリンク(本記述冒頭参照)ならLED出力
#define codeOTNC (0xE800+MODE) // [111 010 ** NNNNNNNN] キャリーフラグが立っていなければLED出力 
#define codeOTC  (0xEC00+MODE) // [111 011 ** NNNNNNNN] キャリーフラグが立っていればLED出力 
#define codeOTNZ (0xF000+MODE) // [111 100 ** NNNNNNNN] ゼロフラグが立っていなければLED出力 
#define codeOTZ  (0xF400+MODE) // [111 101 ** NNNNNNNN] ゼロフラグが立っていればLED出力
#define codeOTNM (0xF800+MODE) // [111 110 ** NNNNNNNN] マイナスフラグが立っていなければLED出力 
#define codeOTM  (0xFC00+MODE) // [111 111 ** NNNNNNNN] マイナスフラグが立っていればLED出力

(2015年1月28日)