プログラムの分岐方法には、「ジャンプテーブル」と呼ばれるテーブルを使った分岐方法があります。ジャンプテーブルは、次のようなアドレスの配列になります。
80010900 fc e0 01 80 0c e1 01 80 18 e1 01 80 34 e1 01 80
プログラムでは、このジャンプテーブルを使って、次のような分岐処理を行います。
8001e0c0 lui v0,#$8001
8001e0c4 addiu s5,v0,#$0900 //s5=#$80010900:ジャンプテーブルのポインタをロード
8001e0c8 lui s1,#$8009
8001e0cc addiu s1,s1,#$0000 //s1=#$80097000
8001e0d0 lw v1,$7bb0(s1) //ジャンプ先を決定する基準値をロード
8001e0d4 nop
8001e0d8 sltiu v0,v1,#$0003
8001e0dc beq v0,zero,$8001e12dc //v1>3より大きかったら$8001e12dcにジャンプ
8001e0e0 nop
8001e0e4 sll v0,v1,#02 //v1×4:オフセットの計算
8001e0e8 addu v0,v0,s5 //v0=v0+s5:ジャンプテーブルのポインタ+オフセット
8001e0ec lw v0,$0000(v0) //ジャンプアドレスをロード
8001e0f0 nop
8001e0f4 jr v0 //v0番地にジャンプ
8001e0f8 nop
8001e0fc lw v0,$7bb0(s1)
8001e100 sw s4,$7bb0(s1)
8001e104 j $8001e214
8001e108 sw s3,$0008(s0)
8001e10c addiu a0,zero,#$0028
8001e110 j $8001e240
8001e114 addu a1,zero,zero
8001e118 addiu a0,zero,#$001c
8001e11c jal $800288d4
8001e120 addu a1,zero,zero
8001e124 lw v0,$7bb0(s1)
8001e128 sw s2,$7bb0(s1)
8001e12c j $8001e214
8001e130 sw s3,$0008(s0)
8001e134 lw v0,$7bb4(s1)
上のソースの場合、レジスタv1にって次のように分岐します・
v1=0のとき、8001e0fcにジャンプ
v1=1のとき、8001e10cにジャンプ
v1=2のとき、8001e118にジャンプ
v1=3のとき、8001e134にジャンプ
もう少し詳しくみてみましょう。
v1=1(アドレス80097bb0の値)のとき、オフセット(sll命令の結果)が「0」になり、8001e0fcに分岐します。
8001e0e4 sll v0,v1,#02 //v1=0のとき「0」
8001e0e8 addu v0,v0,s5 //v0=0+80010900
8001e0ec lw v0,$0000(v0) //v0=8001e0fc(80010900番地からワード値をロード)
8001e0f0 nop
8001e0f4 jr v0 //8001e0fcにジャンプ
v1=2(アドレス80097bb0の値)のときは、オフセット(sll命令の結果)が「4」になり、8001e0fcに分岐します。
8001e0e4 sll v0,v1,#02 //v1=1のとき「4」
8001e0e8 addu v0,v0,s5 //v0=4+80010900
8001e0ec lw v0,$0000(v0) //v0=8001e10c(80010904番地からワード値をロード)
8001e0f0 nop
8001e0f4 jr v0 //8001e10cにジャンプ
同様に、v1=3の時はオフセットが「8」、v1=4の時はオフセットが「c」となり、「ジャンプテーブルのポインタ(先頭アドレス)+オフセット」番地のワード値のアドレスに分岐します。
このv1にロードされる値を制御すれば、ジャンプテーブルに定義されている任意のアドレスにジャンプすることができます。