『 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日)