某改造コード職人さんのコードを見て知らない命令を多数見かけたので
自分なりにわかりそうなものだけ調べてみました

命令のレジスタ(rd,rs,rt)は自然さんで公開されているr5900の表示形式を使わせていただいています。
打ち消し線の部分は私の間違いです。
以前のものを見てしまった人がいると思いますので、間違いの一部を晒してつつ修正をしてあります。

pextlb rd,rs,rt
pext5 rd,rs

ps2disのEEエミュで適当に数値を入れてみてわかったこと

pextlb rd,rs,rt
128ビットrs,rtのダブルワードをバイトデータに分け図のようにする
rs 11223344 55667788
rt 99aabbcc ddeeff00
rd 119922aa 33bb44cc 55dd66ee 77ff8800

使いどころがわからないです…
hとwもできたので試してみました

pextlh rd,rs,rt (pcpyhもどき)
128ビットrs,rtのダブルワードをハーフワードデータに分け図のようにする
rs 11112222 33334444
rt 55556666 77778888
rd 11115555 22226666 33337777 44448888

これも使いどころがわからないと思ったんですが
レジスタを全て同じにした場合のみpcpyhっぽくなってそれなりに使えるかも

まぁとりあえずrd,rs,rtを同じにすると最下位16ビットがqw分コピーされるらしく
pcpyhのqwバージョンで使えるっぽい

ではワードはというと

pextlw rd,rs,rt
128ビットrs,rtのダブルワードをワードデータに分け図のようにする
rs 11112222 33334444
rt 55556666 77778888
rd 11112222 55556666 33334444 77778888

レジスタを全て同じにした場合
これもrd,rs,rtを同じにすると最下位32ビットがqw分コピーされるらしい


pext5 rd,rsはなんとか理解は出来たのですが自分なりの説明が困難ですので
掲載できません。

またしても役に立つか微妙なもの

pmaxh rd,rs,rt
pmaxw rd,rs,rt

pminh rd,rs,rt
pminw rd,rs,rt

これらを使えば最大・最小値と比較命令+分岐(最大・最小値の修正)という処理と同じ事が出来ると思います。

最大値の場合

slti v0,v1,$03e7   最大値と比較
bne v0,zero,$〜   v1が最大値より小さければ分岐
nop         遅延スロット
addiu v1,zero,$03e7 分岐しなかった場合、修正値をv1へ格納
これを

addiu t0,zero,$03e7 最大値
pminh v0,v1,t0    最大値と比較、小さい方をv0へ格納

こうすることでt0とv1比較、小さい方をv0レジスタへ格納(最大値を超えた場合は$03e7)という処理になり、
分岐した場合の処理と分岐しなかった場合の処理を共通で行えるはずですので
スペースを若干少なくできると思います。多分…


最低値(0)の場合

bgez v1,$〜     v1が0以上であれば分岐
nop         遅延スロット
addu v1,zero,zero  分岐しなかった場合、マイナスにならないようzeroをv1へ格納
これも

pmaxh v1,v1,zero   v1とzeroを比較、大きい方をv1レジスタへ格納

こうすることでt0とv1比較、大きい方をv0レジスタへ格納(v1がマイナスの場合はzero)という処理になり、
分岐した場合の処理と分岐しなかった場合の処理を共通で行えるはずですので
スペースを若干少なくできると思います。多分…

またzeroではなくこういう形にしてもいいです
addiu t0,zero,$0003 最小値
pmaxh v1,v1,t0    最小値と比較、大きい方をv1へ格納

これらの処理は最大・最小値への修正しかできないのでコードを作る際にあまり必要ないと思います。
私もたまにしか使用していませんが、pminw,pmaxwが使われているソフトがある事を確認したので使えない事もない様です


ついでに

最大・最小値が設定されていない場合で符号拡張する数値であれば
padssb rd,rs,rt
padssh rd,rs,rt
padssw rd,rs,rt

最大値が設定されていない場合で符号拡張しない数値であれば
padsub rd,rs,rt
padsuh rd,rs,rt
padsuw rd,rs,rt

rs+rt=rdなのでrs,rtどちらかをzeroにしておけば
オーバー・アンダーフローしていきなり符号が変わる、または0になると言う事を防げます
但し使いどころがわからないので私は使用した事はありません

参照箇所の検索(データをアドレスと認識する仕様を利用する)

参照箇所を検索するとアドレスから(_00200000)、(FNC_00200000)等というデータがある箇所又は
ジャンプ元を探す事が出来ますが、この参照箇所の検索を利用する事で16ビット検索の様に特定の数値を
見つける事が可能。

$0064等のよく使われる数値の場合
例えば16ビット検索ではand v1, v1, a000641824この様になっている為にヒットする為
16ビット検索よりこちらを使った方がヒット数を少なくできる場合がある
しかし、(_〜)という箇所以外にもヒットしたり、全てのデータを探せなかったりする場合もあるので、
その点を注意しながらビット検索と使い分けして下さい
これは「逆参照解析さん起動」をしていないとできません

何の役に立つのかというと大抵最大値を超えた場合は最大値に修正される。その時
addiu v0,0,$0064という様な修正値は(_00000064)と表示される
これを探す事が出来、16ビット検索よりヒット数が少ない場合があるという事でそれなりに使える

$0064を探す場合
まずはキーボードのgを押し、アドレス$00000064と入れジャンプ
そうするとアドレス$00100000よりも前になるので白い箇所になり、ワード単位で表示されている
$0064の場合はデータの下1桁が0,4,8,Cなのでこのままでいいが
1,3,5,7…であればb、0,2,4,6…であればhかw(u)という具合にキーボードのu(w)かhかbを押し
w=ワード、h=ハーフワード、b=バイト表記へ変える。理由は1,3,5,7…等をスペースでマークし検索できる様にする為
他にもクアッド・ダブルワードも可

上からb、h、w、d、q

詳しくはps2dis制作者のhanimarさんのサイトのキーアサインを参照

今回の場合64なのでそのままだが、b、h、w、d、qを押した場合アドレス$00100000以降の様に水色に変わり
Shift+uキーで白い状態に戻る。しかしこれはEEエミュを使う時位しか使わないので特に覚えなくても良いです

後は通常の参照箇所の検索の様にスペースキーを押し、F3で参照箇所を探していくとデータ$64がある場所を
見つけてくれる
(上で書いた例外あり)
この方法で16bitのハーフワードではなくワードの数値も可能。あまり意味はないですが…
アドレス$3b9ac9ffへジャンプしbキーでバイト表記。$3b9ac9ffをマークF3で探すという流れ

戻る