\input texi @c -*-texinfo-*-
@c %**start of header
@setfilename simpleprocessor.info
@settitle Simple Processor
@documentencoding EUC-JP
@c %**end of header

@copying
Copyright @copyright{} 2007 Takefumi MIYOSHI, All Rights Reserved.
@end copying

@titlepage
@title Simple Processor
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage

@c Output the table of contents at the begging.
@contents

@ifnottex
@node Top, SimpleProcessor, (dir), (dir)
@top SimpleProcessor

@insertcopying
@end ifnottex

@menu
* SimpleProcessor::             
* 命令コード一覧::              
* プログラミング::              
* 索引:: 


@end menu

@node SimpleProcessor, 命令コード一覧, Top, Top
@comment  node-name,  next,  previous,  up
@chapter SimpleProcessorとは
SimpleProcessorは，単純なRISCプロセッサのシミュレータである．
四則演算や論理演算，メモリアクセス命令をもつ．
また内部にスタックを持ちpop/push命令を使用できる．
      
@section 概要
@cindex 概要，実装クラス
SimpleProcessorは，
@itemize
@item
ExecutableElement
@item
ChannelConnectable
@item
DataBuffer
@end itemize
を実装するクラスである．

@subsection レジスタ構成
@cindex レジスタ構成
SimpleProcessorは，16bit幅のレジスタを32個持っている．レジスタの構成は，次の通り．

@table @code
@item r0〜r28
汎用レジスタ

@item r29
内部のスタックのアドレスを保持するスタックポインタ

@item r30
LDA，STA命令の基点となるアドレスを保持するフレームポインタ

@item r31
プログラムカウンタ
@end table

レジスタは，全てユーザプログラムから自由に操作することができる．

@subsection 基本動作
@cindex 基本動作
@itemize
@item リセット状態でSimpleProcessorはプログラムカウンタが0にセットされる．

@item exec_firstでプロセッサ命令を実行する．

@end itemize


@section 設定ファイル
SimpleProcessorには，プログラム用の内部メモリの大きさおよび，接続するChannelを設定することができる．
最も簡単なSimpleProcessorの構成は次のようになる．

@example
@code{
<element id="proc0" class="net.wasamon.mics.SimpleProcessor" memory="2048"/>
}
@end example

他のデバイスと接続するためのチャネルは，そのアクセスするメモリ番地のoffsetを指定して設定することができる．たとえばChannel，bus0とbus1に2048ずつオフセットをずらして接続する場合には，次のような設定になる．

@example
@code{
<element id="proc0" class="net.wasamon.mics.SimpleProcessor" memory="2048">
  <channel id="bus0" offset="2048"/>
  <channel id="bus1" offset="4096"/>
}
@end example

ここで，Channelは接続先のDataBufferの大きさについての保証をしない．つまり，bus0の先に接続しているDataBufferの大きさが，2048に満たない，たとえば1024で場合，SimpleProcessorから，3072から4095番地にアクセスした場合，それは不正なメモリアクセエス例外を発生する．また逆にbus0の先のDataBufferのサイズが2048を越える場合，bus1へのアクセスエリアとの重なりが生じる．この場合，SimpleProcessorでは，より大きいoffsetで指定した方，つまりbus1へのアクセスとする．


@node 命令コード一覧, プログラミング, SimpleProcessor, Top
@cindex 命令コード
@chapter 命令コード
SimpleProcessorの命令列は，32bit固定長であり，以下のような内容で構成される．

@table @code
@item 命令 rD,rN,rM
8bitの命令と，レジスタ番号rD，rN，rM．

@item 命令 rN,rM
8bitの命令とレジスタ番号，rNとrM．

@item 命令 rN
8bitの命令とレジスタ番号，rN．

@item 命令 rD,imm
8bitの命令とレジスタ番号，16bitの即値imm．

@item 命令 imm
8bitの命令と16bitの即値imm．

@end table

@table @code
@item HALT
プログラムの終了を指示します．この命令を読みこむと，SimpleProcessorはプログラムカウンタを進めません．

@item NOP
何もせず，プログラムカウンタを更新します．

@item ADD rD,rN,rM
レジスタDにレジスタNの内容とレジスタMの内容の和を代入します．

@item ADDI rD,imm
レジスタDにレジスタDの内容と即値immを加算した結果を代入します．

@item SUB rD,rN,rM
レジスタDにレジスタNの内容とレジスタMの内容の差を代入します．

@item SUBI rD,imm
レジスタDにレジスタDの内容から即値immを引いた値を代入します．

@item MULT rD,rN,rM
レジスタNとレジスタMの積を求め，その下位16bitをレジスタDに，上位16bitをレジスタ(D+1)に代入します．

@item DIV rD,rN,rM
レジスタNとレジスタMの除算を行い，その商をレジスタDに，余を16bitをレジスタ(D+1)に代入します．

@item OR rD,rN,rM
レジスタDにレジスタNとレジスタMの各ビットでの論理和を代入します．

@item AND  
レジスタDにレジスタNとレジスタMの各ビットでの論理積を代入します．

@item JMP rN
レジスタNのアドレス番地にプログラムカウンタをセットします．

@item JMPI imm(16bit)
即値で指定したアドレス番地にプログラムカウンタをセットします．

@item JCC rN
SimpleProcessor内のconditionフラグが真の場合にレジスタNのアドレス番地にプログラムカウンタをセットします．

@item JCCI imm
SimpleProcessor内のconditionフラグが真の場合にimm番地にプログラムカウンタをセットします．

@item EQ rD,rN,rM
レジスタNとレジスタMの値が等しい場合にconditionフラグを真にし，レジスタDに0を代入する．

@item NEQ rD,rN,rM
レジスタNとレジスタMの値が等しくない場合にconditionフラグを真にし，レジスタDに0を代入する．

@item LT rD,rN,rM
レジスタNがレジスタMより小さい場合にconditionフラグを真にし，レジスタDに0を代入する．

@item GT rD,rN,rM
レジスタNがレジスタMより大きい場合にconditionフラグを真にし，レジスタDに0を代入する．

@item LEQ rD,rN,rM
レジスタNがレジスタM以下の場合にconditionフラグを真にし，レジスタDに0を代入する．

@item GEQ rD,rN,rM
レジスタNがレジスタM以上の場合にconditionフラグを真にし，レジスタDに0を代入する．

@item LDR rN,rM
レジスタNの番地のデータを読み込み，レジスタMに代入する．外部Channelへのリクエストの場合，writeback()でレジスタMにデータは書き戻される．

@item STR rN,rM
レジスタNの番地にレジスタMのデータを書き込む．

@item MOV rD,rN
レジスタNの値をレジスタDに転送する．

@item MOVI rD,imm
レジスタDに即値immを転送する．

@item POP rD
スタックからデータをpopし，レジスタDに転送する．

@item PUSH rN
スタックにレジスタNの値をpushする．

@item CALL rN
レジスタN番地からの命令を呼び出す．現在のプログラムカウンタはスタックにpushされる．

@item CALLI imm
即値imm番地からの命令を呼び出す．現在のプログラムカウンタはスタックにpushされる．

@item RET
スタックから値をpopし，その値をプログラムカウンタとする

@item LDA rD,imm
フレームポインタの値から即値immで指定したオフセット位置の番地の値を読み込みレジスタDに書き込む．

@item STA rN,imm
フレームポインタの値から即値immで指定したオフセット位置の番地にレジスタNの値を書き込む．

@end table

@node プログラミング, 索引, 命令コード一覧, Top
@chapter プログラミング

@section アセンブリ言語書式

@subsection 命令列の構成
命令列は，命令とラベルから成る．
ラベルは，@code{ラベル:}と行頭からはじまり@code{:}でおわる．
また命令列は

@code{
命令 オペランド,オペランド,オペランド
}

と命令の後の空白に続いて必要なオペランドを@code{,}で区切って列挙する．オペランドに用いられる文字列を次に示す．

@table @code
@item レジスタ番号
レジスタ番号を指定するためには，プリフィクスとして@code{r}を指定して，@code{r0}のように記述する．

@item 数値
数値は即値として扱われる．

@item ラベル
文字列は，ラベルとして処理される．使用するラベルは，既に宣言済みでなければならない．

@end table

@section スタックの使い方

SimpleProcessorでは，内部に持っているスタックを利用することができる．これは，@code{PUSH}や@code{POP}だけではなく，@code{CALL}，@code{CALLI}および@code{RET}を実行する場合にも使用される．そのため，これらを命令を使用する場合には，スタックポイインタを予じめ適切に設定しておく必要がある．そのコードは，たとえば，次の通り．

@example
@code{
	movi	r29,2047
}
@end example


ここでは，2047番地をスタックのトップとしているが，メモリの大きさなどによって，この値は変わるべきである．

@section フレームポインタ
フレームポインタは，@code{LDA}や@code{STA}命令でアクセスする際のオフセットの起点となるアドレスである．関数呼び出し等と連携して有用に活用するためには，初期状態として，スタックポインタと同一の値にしておくのが望ましい．

@section 関数呼び出しの方法

関数呼び出しの際には，呼出し元のレジスタの退避，復帰アドレスなどを適切に設定する必要がある．次に示すのは，1引数の関数を呼び出す場合の単純な方法である．戻り値はレジスタで返すものとしている．

@example
@code{
        push r0     ; 退避したいレジスタをスタックに積む
        push r5     ; 関数の引数をスタックに積む
        calli _func ; ラベルを指定する場合，接頭辞に'_'が必要
        addi r29,1  ; 引数の分だけスタックポインタを戻す
        ...
func:
        push r30    ; フレームポインタをスタックに積む
        mov r30,r29 ; スタックポインタを新しいフレームポインタとする
        addi r29,-2 ; この関数内で使う変数を保持する領域をスタック上に作る(ここでは，2ワード分確保)
        lda r5,2    ; 関数の引数はフレームポインタ+2の位置にある．ちなみに+0は\\戻りアドレス，+1は旧フレームポインタ
        ...
        mov r29,r30 ; スタックポインタをフレームポインタに戻す
        pop r30     ; 旧フレームポインタをフレームポインタレジスタに書き戻す
        ret         ; 戻りアドレスに帰る
}
@end example

fpとspを活用して，関数のプロログ部分で，その関数で使用する変数を保持するために\\必要な分だけスタックポインタを減じ，空いたスタック領域にSTA/LDA命令でアクセスす\ることでローカル変数を簡単に扱うこともできる．

@node 索引,  , プログラミング, Top
@unnumbered 索引

@printindex cp

@bye
