Download presentation
Presentation is loading. Please wait.
1
計算機構成 第7回 サブルーチンコールとスタック テキストp85-90
情報工学科 天野英晴
2
サブルーチンコール メインルーチン A サブルーチンは呼ばれた所に 戻っていく 違った場所で呼べる ソフトウェアのモジュール化が可能
現在のプログラムでは不可欠 call A return call A サブルーチンコール命令の 実装における選択 →戻り番地(pc+1)を どこにしまうか?
3
Jump and Link 戻り番地を最大番号のレジスタに保存 JAL X : pc←pc+1+X, r7←pc+1 POCOの場合r7
古典的な手法でマインフレーム時代に使われた Branch and Link命令 RISCで最も良く使われる方式 JAL X : pc←pc+1+X, r7←pc+1 10101 XXXXXXXX 飛ぶ範囲はJMPと同じく11ビット(-1024~1023) 議論1:サブルーチンの入れ子(ネスト)に対応しない 議論2:r7にしまうのは命令の直交性を損ねる(格好わるい)
4
2乗を計算する例 LDIU r0,#0 LD r1,(r0) MV r2,r1 r1とr2に同じ値をセットする JAL mult
end: JMP end // Subroutine Mult r3 ← r1×r2 ここでr2は破壊される mult: LDIU r3,#0 loop: ADD r3,r1 ADDI r2,#-1 BNZ r2, loop JR r7
5
POCOのサブルーチンコール メインルーチン A リターン命令にはJR r7が利用可能 ここで疑問: サブルーチンの中で別のサブルーチン を呼ぶとr7が壊れて戻れなくなるのでは? その通り! しかし他にも壊れては困るレジスタは あるはず →保存するためにスタックが必要 JAL B? JAL A JR r7 JAL A
6
スタック データを積む棚 LIFO(Last In First Out)、FILO(First In Last Out)とも呼ばれる
push操作でデータを積み pop操作で取り出す LIFO(Last In First Out)、FILO(First In Last Out)とも呼ばれる 演算スタックとは違う(誤解しないで!) 主記憶上にスタック領域が確保される C C push pop B C B A B A A
7
Bでは r0,r1が 壊れる スタックを使った入れ子構造への対応 メインルーチン B push r0, push r1 A r1 push r0, push r7 r0 r7 JAL B r0 r7 pop r1, pop r0 JAL A r0 JAL C JR r7 pop r7, pop r0 JR r7 Cでは r1,r2が 壊れる JAL A Aでは r0,r7が 壊れる C push r1, push r2 r2 r1 r7 壊れるレジスタをサブルーチンの 入り口でpushして保存し、 出口でpopして復帰 → 呼ぶ方で保存する方法もある r0 pop r2, pop r1 JR r7
8
スタックの実現(push) r6をスタックポインタとする スタックポインタをマイナスしてからSTする push 0、push 1は
ADDI r6,#-1 ST r0,(r6) ST r1,(r6) r1 r0 r6 r1 スタック領域 r0 r6
9
スタックの実現(pop) スタック領域はメモリの番地の小さい方に伸びる→昔からの習慣 pop操作は、LDしてからスタックポインタを+する。
LD r1(r6) ADDI r6,#1 LD r0,(r6) r1 r6 r1 r0 r0 r6
10
2乗を計算する例 r2を破壊しないサブルーチンコール r6はメインルーチンで初期化する必要がある
// Subroutine Mult r3 ← r1×r2 mult: ADDI r6,#-1 ST r2,(r6) LDIU r3,#0 loop: ADD r3,r1 ADDI r2,#-1 BNZ r2, loop LD r2,(r6) ADDI r6,#1 JR r7
11
JALを巡る議論 戻り番地を汎用レジスタに格納する方針 ではr7に決めちゃうのはどうなの? どっちみちスタックに汎用レジスタにしまう
ならば入れ子になるときには、r7もついでにしまってやれば良い システムスタックを持っていてCall時にこれにしまう方法(IA32などの方法)と比べて劣ってはいない→むしろ不必要なメモリ読み書きが減る ではr7に決めちゃうのはどうなの? 任意のレジスタにしまうことができても意味がない JALはできるだけ遠くに飛びたいのでレジスタのフィールドはないほうが良い 多少の格好の悪さは我慢しよう!
12
JAL命令のVerilog記述 pcをr7に保存する
assign rf_c = ld_op ? ddatin: jal_op ? pc+1: alu_y; assign rwe = ld_op | alu_op…| jal_op; assign cadr = jal_op? 3’b111 : rd; rfile rfile_1(.clk(clk), .a(rf_a), .aadr(rd), .b(rf_b), .badr(rs), .cadr(cadr), .we(rwe); 今までと異なりレジスタファイルのaadr=cadrではなくなる。この二つを分離する必要がある
13
JALのVerilog記述 飛び方はJMPと同じ always @(posedge clk or negedge rst_n) begin
if(!rst_n) pc <= 0; else if ((bez_op & rf_a == 16’b0) | (bnz_op & rf_a != 16’b0) | (bpl_op & ~rf_a[15]) | (bmi_op & rf_a[15])) pc<=pc+{{8imm[7]}},imm}+1; else if (jmp_op| jal_op) pc <= pc +{{5{idatain[10]}},idatain[10:0]}}+1; else if(jr_op) pc <= rf_a; else pc<=pc+1; end
14
NOP MV rd,rs rd← rs AND rd,rs rd← rd AND rs OR rd,rs rd← rd OR rs
MV rd,rs rd← rs 00000dddsss00001 AND rd,rs rd← rd AND rs 00000dddsss00010 OR rd,rs rd← rd OR rs 00000dddsss00011 SL rd rd← rd<<1 00000ddd SR rd rd← rd>>1 00000ddd ADD rd,rs rd← rd + rs 00000dddsss00110 SUB rd,rs rd← rd - rs 00000dddsss00111 ST rd,(ra) (ra)← rd 00000dddaaa01000 LD rd,(ra) rd← (ra) 00000dddaaa01001 JR rd pc ← rd 00000ddd
15
LDI rd,#X rd← X(符号拡張) LDIU rd,rs rd← X(ゼロ拡張) ADDI rd,#X rd←rd+X(符号拡張)
01000dddXXXXXXXX LDIU rd,rs rd← X(ゼロ拡張) 01001dddXXXXXXXX ADDI rd,#X rd←rd+X(符号拡張) 01100dddXXXXXXXX ADDIU rd,#X rd←rd+X(ゼロ拡張) 01101dddXXXXXXXX LDHI rd,#X rd←{X,0} 01010dddXXXXXXXX BEZ rd,X if(rd=0) pc←pc+X+1 10000dddXXXXXXXX BNZ rd,X if(rd≠0) pc←pc+X+1 10001dddXXXXXXXX BPL rd,X if(rd>=0) pc←pc+X+1 10010dddXXXXXXXX BMI rd,X if(rd<0) pc←pc+X+1 10011dddXXXXXXXX
16
JMP #X pc←pc+X+1 JAL #X 10100XXXXXXXXXXX pc←pc+X+1, r7←pc+1
17
演習 1.multを利用して0番地の数の3乗を計算せよ
2.JALR rdは、JAL同様r7に戻り番地をしまってJR同様rdの中身の番地にそのまま飛ぶ命令である。これを実装せよ。 JALR rd 00000ddd
Similar presentations
© 2024 slidesplayer.net Inc.
All rights reserved.