2014年12月23日火曜日

MIPSアーキテクチャにおける命令

ほとんど「計算機工学」の講義の受け売りですが、MIPSアーキテクチャについて
メモ程度に、軽く書きます。
内容も微妙ですので、自分用のメモみたいな記事になってしまいました。また、HTMLもぐちゃぐちゃです。

でも、せっかく書いたので公開します

MIPSの命令セットは、

MIPS "Green Sheet"

からダウンロードできます。

MIPSは3オペランド命令のみ実行できます。たとえば加算命令adduにおいて、
    addu $t0, $s1, $s2
演算対象である$s1, $s2と、結果の代入先$t0はすべてオペランド(operand)と呼ばれます。MIPSにおいては、このオペランドが必ず3つです。

演算はレジスタに保存された値しかできません。即値に対して演算を行うには、レジスタにロードする必要があります。

MIPSの命令コードは必ず32ビットです

MIPSのレジスタは32個あり、GreenSheetの1ページ目右下に示されるように、零レジスタ、一時変数用レジスタ、OS用レジスタなど、用途が割り当てられています。

<命令コードの形式>
アセンブリ言語を数値化したものを命令コードという

命令により、レジスタ型命令(R)、即値型命令(I)、ジャンプ型命令(J)に分類される


 ・R形式
内容:           op   rs   rt   rd   shamt   funct
ビット数:     6     5    5    5       5         6

op……オペレータ(演算子)
rs,rt……演算対象のレジスタ
rd……計算結果の代入先レジスタ(destination operand)
shamt……シフト命令におけるシフト量
funct……演算の種類(GreenSheetの2ページ目は見にくいので、MIPS Instruction Referenceを参照)

R形式の時、opは必ず0b000000

 ・I形式
内容:           op   rs   rt   const
ビット数:     6     5    5     16

即値(定数)を表現できる
rsはR形式でのrsだが、rtはR形式でのrd
constは定数で、16ビットまで表現可能

・J形式
内容:           op   target
ビット数:     6       26

targetでジャンプ先アドレスを表す
opはjなら2(0b000010)、jalなら3(0b000011)

<基本命令>
命令の右端にiがつくとimmediateの略であり、I形式であることを示します。
ここではiのつかないものを示します

lw $t0, 1200($t1)
32ビット読み込み(load word)
I形式で、opは35

add $t0, $t1, $t2
$t1と$t2を加算した結果を$t0に代入
加算前に符号拡張される。すなわち、桁数が足りない場合、最上位ビットをそれより上のビットに対してコピーする
R形式で、opは32

sub $t0, $t1, $t2
$t1-$t2の結果を$t0に代入
R形式で、opは34

lui $t0
上位16ビットにロード(load upper immediate)
下位16ビットは0で埋める
I形式

sll $
左シフト(shift left logical)
下位ビットは0で埋める

srl $
右シフト(shift right logical)
上位ビットは符号ビットで埋める

slt $s1, $s2, $s3
大小比較を行う(set on less than)
C言語では
if( $s2 < $s3){ $s1 = 1; }else{ $s1 = 0;}
のようなかんじ

beq $t0, $t1, label
$t0と$t1が等しければlabelへ分岐(branch if equal)

bne $t0, $t1, label
$t0と$t1が等しければlabelへ分岐(branch if not equal)

j label
labelへジャンプ
J形式


<擬似命令>
実行可能なコードの組み合わせで実行する処理を、アセンブリにおいてはひとつの命令のように表記することができます

・大きな即値をレジスタに代入するとき
*li (load immediate)
    lui $s0, 61
    ori $s0, $s0, 2304

これで代入したい即値xの上位16ビット:61 = 0b0000000000111101、および下位16ビット:2304 = 0b0000100100000000を用いて、
$s0 = 00000000001111010000100100000000 = xを実現できます

・ループする時
    Loop: (内容)
     j      Loop

・分岐するとき
    beq $t0, $t1, label1
    j label2
    label1: (if)
    label2: (else)

これを

・絶対値を求めるとき
 *標準(分岐を用いる)
    slt $t0, $t1, $zero
    beq $t0, $zero, label
    sub $t0, $zero, $t1
    j Exit
    label: addi $t0, $zero, $t1
    Exit:





*高速ver
    srl $t2, $t1, 31
    xor $t0, $t0, $t1
    sub $t0, $t0, $t2




これの高速verを機械語にすると
000000 00000 01001 11111 00000 000010
000000 01000 01001 01000 00000 100110
000000 01000 01010 01000 00000 100010


ここで、srlは即値を用いているように見えますが、shamtに代入しているため、R形式を用います。また、rdは00000にしておきます。




・ビット反転
いわゆるNOT演算
3オペランド命令として、norなどで代用します。
    nor $t0, $t1, $zero

これで$t0への$t1のビット反転結果を代入を実現できます。


・変数コピー
    add $t0, $t1, $zero

これで$t1への$t0のコピーを実現できます。



・なにもしないとき
何もしない命令nop(no operation)が用意されています。
nopの命令コードは00000000000000000000000000000000です。
すなわち、R形式であり、
    sll $zero, $zero, $zero
を表します。

中途半端ですがこのへんで!




0 件のコメント:

コメントを投稿