mtc0 $0,$28 /* TagLo */ mtc0 $0,$29 /* TagHi */ li $2,0x80000000 li $3,0x80004000 /* 容量が16Kバイトの場合 */ loop: cache 0x09,0($2) /* Index Store Tag Dcache */ addiu $2,$2,0x10 /* ライン・サイズが32バイトと分かっている場合は0x20を加算すればよい */ bne $2,$3,loop nopでよいことになります.この命令列ではウェイに関する情報はありません.もっとも,キャッシュが2ウェイであることを知っていれば,ウェイ0とウェイ1を同時に初期化する次のような命令列も考えられます.
mtc0 $0,$28 /* TagLo */ mtc0 $0,$29 /* TagHi */ li $2,0x80000000 li $3,0x80002000 /* 容量が16Kバイトの場合 */ loop: cache 0x09,0x0000($2)/* Index Store Tag Dcache way-0 */ cache 0x09,0x2000($2)/* Index Store Tag Dcache way-1 */ addiu $2,$2,0x10 /* ライン・サイズが32バイトと分かっている場合は0x20を加算すればよい */ bne $2,$3,loop nopリストAのプログラムではキャッシュを初期化するために,Index Store Tag操作ではなく,Index Writeback Invalidate操作を使用しています.Index Store Tagの場合,キャッシュ・ラインがDirtyであっても強制的にタグを0にするので,Dirtyなキャッシュ・ラインはメイン・メモリにライトバックされないまま消えてしまいます.
li $2,addr cache 0x11,0($2) /* Hit Invalidate Dcache */あるいは,
li $2,addr cache 0x15,0($2) /* Hit Writeback Invalidate Dcache */です.Hit Writeback Invalidate操作が無効化するキャッシュ・ラインがDirtyな場合,その内容をライトバックしてから無効化を行うのに対して,Hit Invalidate操作はキャッシュ・ラインがDirtyであるかないかにかかわらず(ライトバックを行わず)に無効化を行います.
li $2,addr cache 0x01,0x0000($2) /* Index Writeback Invalidate Dcache */ cache 0x01,0x2000($2) /* Index Writeback Invalidate Dcache */のようになります.1番目のCACHE命令がウェイ0と1のどちらを無効化しているかは,指定する仮想アドレス(今の場合はaddr)に依存します.仮想アドレスaddrのビット13が0の場合は,1番目のCACHE命令がウェイ0,2番目のキャッシュ命令がウェイ1を示しています.もし仮想アドレスaddrのビット13が1の場合は,ウェイの0と1が逆になります.いずれにしろ,二つのCACHE命令でウェイ0とウェイ1の両方を指定していることには変わりません.
li $2.addr cache 0x19,0($2)さて,リストAのプログラムの実行結果を図Aに示します.得られるタイマの値が小さいほど実行時間が短いことを意味するので,ラインサイズ32バイトの方が16バイトのときよりも約39%(6294633/4524888=1.39)高速に処理できることがわかります.
# loads ## Ready for S-Record download ... .. ## First Load Addr = 0x80200000 ## Last Load Addr = 0x80200CA9 ## Total Size = 0x00000CAA = 3242 Bytes ## Start Addr = 0x80200000 # go 80200000 ## Starting application at 0x80200000 ... line size=16 time=6294633 line size=32 time=4524888 ## Application terminated, rc = 0x0 #
# loads ## Ready for S-Record download ... .. ## First Load Addr = 0x80000000 ## Last Load Addr = 0x80000FAF ## Total Size = 0x00000FB0 = 4016 Bytes ## Start Addr = 0x80000000 # go 80000000 ## Starting application at 0x80000000 ... Making Source Data CSI Setup DMA Start Wait for Interrupt Interrupt Occurred! R_P1STP Checking Destination Data DMA Result is NG! ## Application terminated, rc = 0x0 # md a0210000 20 a0210000: 00010000 00030002 00050004 00070006 ................ a0210010: 00090008 000b000a 000d000c 000f000e ................ a0210020: 00110010 00130012 00150014 00170016 ................ a0210030: 00190018 001b001a 001d001c 001f001e ................ a0210040: 00210020 00230022 00250024 00270026 .!.".#.$.%.&.'. a0210050: 00290028 002b002a 002d002c 002f002e (.).*.+.,.-.../. a0210060: 00310030 00330032 00350034 00370036 0.1.2.3.4.5.6.7. a0210070: 00390038 003b003a 003d003c 003f003e 8.9.:.;.<.=.>.?. # md a0220000 20 a0220000: ffffffff ffffffff ffffffff ffffffff ................ a0220010: ffffffff ffffffff ffffffff ffffffff ................ a0220020: ffffffff ffffffff ffffffff ffffffff ................ a0220030: ffffffff ffffffff ffffffff ffffffff ................ a0220040: ffffffff ffffffff ffffffff ffffffff ................ a0220050: ffffffff ffffffff ffffffff ffffffff ................ a0220060: ffffffff ffffffff ffffffff ffffffff ................ a0220070: ffffffff ffffffff ffffffff ffffffff ................ #※LoopBackしてないので比較結果はNGになります.
extern _gp; asm("la $28,_gp");external宣言とasm文です.これによってプログラムの実行前にグローバル・ポインタ($28)を設定することができるようになります.実際にグローバル・ポインタをどのアドレスに割り付けるかはリンカに与えるコマンド・ファイル内に記述します.リストDがそのリンカ・スクリプト・ファイルです.
# loads ## Ready for S-Record download ... ......................... ## First Load Addr = 0x80200000 ## Last Load Addr = 0x80209F5F ## Total Size = 0x00009F60 = 40800 Bytes ## Start Addr = 0x80200000 # go 80200000 ## Starting application at 0x80200000 ... bfc00000 100000ff : beq r0,r0,0xbfc00400 bfc00004 00000000 : nop bfc00008 100000fd : beq r0,r0,0xbfc00400 bfc0000c 00000000 : nop bfc00010 10000149 : beq r0,r0,0xbfc00538 bfc00014 00000000 : nop bfc00018 10000147 : beq r0,r0,0xbfc00538 bfc0001c 00000000 : nop bfc00020 10000145 : beq r0,r0,0xbfc00538 bfc00024 00000000 : nop bfc00028 10000143 : beq r0,r0,0xbfc00538 bfc0002c 00000000 : nop bfc00030 10000141 : beq r0,r0,0xbfc00538 bfc00034 00000000 : nop bfc00038 1000013f : beq r0,r0,0xbfc00538 bfc0003c 00000000 : nop bfc00040 1000013d : beq r0,r0,0xbfc00538 bfc00044 00000000 : nop bfc00048 1000013b : beq r0,r0,0xbfc00538 bfc0004c 00000000 : nop 80200000 3c1c8021 : lui r28,0x8021 80200004 0808008e : j 0x80200238 80200008 279c9f60 : addiu r28,r28,-0x60a0 8020000c 3c02af00 : lui r2,0xaf00 80200010 308400ff : andi r4,r4,0x00ff 80200014 34450800 : ori r5,r2,0x0800 80200018 34430805 : ori r3,r2,0x0805 8020001c 90620000 : lbu r2,0(r3) 80200020 30420020 : andi r2,r2,0x0020 80200024 1040fffd : beq r2,r0,0x8020001c 80200028 00000000 : nop 8020002c 03e00008 : jr r31 80200030 a0a40000 : sb r4,0(r5) 80200034 3c02af00 : lui r2,0xaf00 80200038 34440809 : ori r4,r2,0x0809 8020003c 24030001 : addiu r3,r0,0x0001 80200040 a0830000 : sb r3,0(r4) 80200044 34450803 : ori r5,r2,0x0803 80200048 a0800000 : sb r0,0(r4) 8020004c 34460801 : ori r6,r2,0x0801 ## Application terminated, rc = 0x0 #
# loads ## Ready for S-Record download ... .... ## First Load Addr = 0x80200000 ## Last Load Addr = 0x80201E67 ## Total Size = 0x00001E68 = 7784 Bytes ## Start Addr = 0x80200000 # go 80200000 ## Starting application at 0x80200000 ... # go 80200000 ## Starting application at 0x80200000 ... ->1+2+3 = 6 ->1-2-3 = -4 ->1+2*3+4*5 = 27 ->(1+2)*(3+4)-(4+3)*(2-1) = 14 ->q = 0 ## Application terminated, rc = 0x0 #