全部で309命令+3命令だと思う(数え間違いがなければ...)
要素幅EEWとレジスタグループ幅LMULとはほぼ直交しているのでIntrinsicにすると1万命令くらいある。
実装的にはレジスタグループを考えなければ簡単な部類な命令が多い。 64bit整数の乗算/積和とか128bitの固定少数右シフトは回路面積が大きくなるのでuopに分解したほうがよさげ。
害悪ポイントはLMUL=8本でSEW=8bitの時のvrgatherei16.vv。スクラッチパッドのSRAMに書き出して読み出す実装ならレジスタの幅分だけのサイクル数がかかる。(vlen=128bitなら128cycle)
slideup/downは適当にレーン間の接続網(ringでもtorusでも)組んでやればいい気がする。
設定命令
vsetvli rd, rs1, vtypei vsetivli rd, uimm, vtypei vsetvl rd, rs1, rs2
Load Store命令
アライメント制約は要素サイズでありVLENではない。
vtypeのSEWは関係なく命令に直接エンコードされる。これによってvtypeを変える回数が減らせる。
Unit Stride 命令
vle8.v vd, (rs1), vm vle16.v vd, (rs1), vm vle32.v vd, (rs1), vm vle64.v vd, (rs1), vm vse8.v vs3, (rs1), vm vse16.v vs3, (rs1), vm vse32.v vs3, (rs1), vm vse64.v vs3, (rs1), vm
Strided 命令
Stride幅の制約は"整数"のバイト数(インデックスではない)なので0でも負でもいい。
vlse8.v vd, (rs1), rs2, vm vlse16.v vd, (rs1), rs2, vm vlse32.v vd, (rs1), rs2, vm vlse64.v vd, (rs1), rs2, vm vse8.v vs3, (rs1), rs2, vm vse16.v vs3, (rs1), rs2, vm vse32.v vs3, (rs1), rs2, vm vse64.v vs3, (rs1), rs2, vm
Indexed 命令
俗にいうGather、Scatter。vs2はバイト数を示す。
vluxei8.v vd, (rs1), vs2, vm vluxei16.v vd, (rs1), vs2, vm vluxei32.v vd, (rs1), vs2, vm vluxei64.v vd, (rs1), vs2, vm vloxei8.v vd, (rs1), vs2, vm vloxei16.v vd, (rs1), vs2, vm vloxei32.v vd, (rs1), vs2, vm vloxei64.v vd, (rs1), vs2, vm vsuxei8.v vs3, (rs1), vs2, vm vsuxei16.v vs3, (rs1), vs2, vm vsuxei32.v vs3, (rs1), vs2, vm vsuxei64.v vs3, (rs1), vs2, vm vsoxei8.v vs3, (rs1), vs2, vm vsoxei16.v vs3, (rs1), vs2, vm vsoxei32.v vs3, (rs1), vs2, vm vsoxei64.v vs3, (rs1), vs2, vm
順序あり(ordered)となし(unordered)がある。
Unit Stride Fault-Only-First Load 命令
先頭0番目の要素のみ例外をトラップさせる。それ以降で例外が発生した場合、ベクトル長vlを発生した箇所にする。
vle8ff.v vd, (rs1), vm vle16ff.v vd, (rs1), vm vle32ff.v vd, (rs1), vm vle64ff.v vd, (rs1), vm
Unit-Stride Segment 命令
SoA(Structure of Array)をAoS(Array of Structure)に変換する。
vlseg<nf>e<eew>.v vd, (rs1), vm vsseg<nf>e<eew>.v vs3, (rs1), vm
<nf>={1,2,3,4,5,6,7,8}
<eew>={8,16,32,64}
nf本のレジスタに書き込みが発生する。
Strided Segment命令
Stride幅付きのSegment命令
vlsseg<nf>e<eew>.v vd, (rs1), rs2, vm vssseg<nf>e<eew>.v vs3, (rs1), rs2, vm
<nf>={1,2,3,4,5,6,7,8}
<eew>={8,16,32,64}
Indexed Segment命令
Segment命令のGather、Scatter
vluxseg<nf>ei<eew>.v vd, (rs1), vs2, vm vloxseg<nf>ei<eew>.v vd, (rs1), vs2, vm vsuxseg<nf>ei<eew>.v vs3, (rs1), vs2, vm vsoxseg<nf>ei<eew>.v vs3, (rs1), vs2, vm
順序あり(ordered)となし(unordered)がある。
<nf>={1,2,3,4,5,6,7,8}
<eew>={8,16,32,64}
ロード命令はvd != vs2でないといけない(例外からの再開のため)
Whole Register命令
vlとかvtypeも関係なくベクトルレジスタをロードストアする。nfは一括で処理するレジスタ数
vl<nf>re<eew>.v vd, (rs1) vs<nf>r.v vs3, (rs1)
<nf>={1,2,3,4,5,6,7,8}
<eew>={8,16,32,64}
要素幅EEWは命令の動作に関係ない。ただのヒントらしい。
整数演算
加減算
vadd.vv vd, vs2, vs1, vm vadd.vx vd, vs2, rs1, vm vadd.vi vd, vs2, imm, vm vsub.vv vd, vs2, vs1, vm # vd[i] = vs2[i] - vs1[i] vsub.vx vd, vs2, rs1, vm # vd[i] = vs2[i] - x[rs1] vrsub.vv vd, vs2, rs1, vm # vd[i] = x[rs1] - vs2[i] vrsub.vx vd, vs2, imm, vm # vd[i] = imm - vs2[i]
拡幅加減算
等幅±等幅→倍幅
vwaddu.vv vd, vs2, vs1, vm vwaddu.vx vd, vs2, rs1, vm vwsubu.vv vd, vs2, vs1, vm vwsubu.vx vd, vs2, rs1, vm vwadd.vv vd, vs2, vs1, vm vwadd.vx vd, vs2, rs1, vm vwsub.vv vd, vs2, vs1, vm vwsub.vx vd, vs2, rs1, vm
倍幅±等幅→倍幅
vwaddu.wv vd, vs2, vs1, vm vwaddu.wx vd, vs2, rs1, vm vwsubu.wv vd, vs2, vs1, vm vwsubu.wx vd, vs2, rs1, vm vwadd.wv vd, vs2, vs1, vm vwadd.wx vd, vs2, rs1, vm vwsub.wv vd, vs2, vs1, vm vwsub.wx vd, vs2, rs1, vm
整数拡張
SEWはvdに適用される。
vs2の要素幅はSEWの1/2、1/4、1/8になる。
vzext.vf2 vd, vs2, vm vsext.vf2 vd, vs2, vm vzext.vf4 vd, vs2, vm vsext.vf4 vd, vs2, vm vzext.vf8 vd, vs2, vm vsext.vf8 vd, vs2, vm
キャリー(ボロー)付き加減算
マスクレジスタv0からキャリーを読み出し、vmadc vmsbcでレジスタにキャリーを入れる。
vadc.vvm vd, vs2, vs1, v0 vadc.vxm vd, vs2, rs1, v0 vadc.vim vd, vs2, imm, v0 vmadc.vvm vd, vs2, vs1, v0 vmadc.vxm vd, vs2, rs1, v0 vmadc.vim vd, vs2, imm, v0 vmadc.vv vd, vs2, vs1 vmadc.vx vd, vs2, rs1 vmadc.vi vd, vs2, imm
vsbc.vvm vd, vs2, vs1, v0 vsbc.vxm vd, vs2, rs1, v0 vmsbc.vvm vd, vs2, vs1, v0 vmsbc.vxm vd, vs2, rs1, v0 vmsbc.vv vd, vs2, vs1 vmsbc.vx vd, vs2, rs1
論理演算
vand.vv vd, vs2, vs1, vm vand.vx vd, vs2, rs1, vm vand.vi vd, vs2, imm, vm vor.vv vd, vs2, vs1, vm vor.vx vd, vs2, rs1, vm vor.vi vd, vs2, imm, vm vxor.vv vd, vs2, vs1, vm vxor.vx vd, vs2, rs1, vm vxor.vi vd, vs2, imm, vm
シフト演算
vsll.vv vd, vs2, vs1, vm vsll.vx vd, vs2, rs1, vm vsll.vi vd, vs2, uimm, vm vsrl.vv vd, vs2, vs1, vm vsrl.vx vd, vs2, rs1, vm vsrl.vi vd, vs2, uimm, vm vsra.vv vd, vs2, vs1, vm vsra.vx vd, vs2, rs1, vm vsra.vi vd, vs2, uimm, vm
狭幅シフト演算
倍幅>>等幅→等幅
vnsrl.wv vd, vs2, vs1, vm vnsrl.wx vd, vs2, rs1, vm vnsrl.wi vd, vs2, uimm, vm vnsra.wv vd, vs2, vs1, vm vnsra.wx vd, vs2, rs1, vm vnsra.wi vd, vs2, uimm, vm
比較演算
vmseq.vv vd, vs2, vs1, vm vmseq.vx vd, vs2, rs1, vm vmseq.vi vd, vs2, imm, vm vmsne.vv vd, vs2, vs1, vm vmsne.vx vd, vs2, rs1, vm vmsne.vi vd, vs2, imm, vm vmsltu.vv vd, vs2, vs1, vm vmsltu.vx vd, vs2, rs1, vm vmslt.vv vd, vs2, vs1, vm vmslt.vx vd, vs2, rs1, vm vmsleu.vv vd, vs2, vs1, vm vmsleu.vx vd, vs2, rs1, vm vmsleu.vi vd, vs2, imm, vm vmsle.vv vd, vs2, vs1, vm vmsle.vx vd, vs2, rs1, vm vmsle.vi vd, vs2, imm, vm vmsgtu.vx vd, vs2, rs1, vm vmsgtu.vi vd, vs2, imm, vm vmsgt.vx vd, vs2, rs1, vm vmsgt.vi vd, vs2, imm, vm
min/max
vminu.vv vd, vs2, vs1, vm vminu.vx vd, vs2, rs1, vm vmin.vv vd, vs2, vs1, vm vmin.vx vd, vs2, rs1, vm vmaxu.vv vd, vs2, vs1, vm vmaxu.vx vd, vs2, rs1, vm vmax.vv vd, vs2, vs1, vm vmax.vx vd, vs2, rs1, vm
乗算
vmul.vv vd, vs2, vs1, vm vmul.vx vd, vs2, rs1, vm vmulh.vv vd, vs2, vs1, vm vmulh.vx vd, vs2, rs1, vm vmulhu.vv vd, vs2, vs1, vm vmulhu.vx vd, vs2, rs1, vm vmulhsu.vv vd, vs2, vs1, vm vmulhsu.vx vd, vs2, rs1, vm
64bit乗算器実装したくないな...
除算/剰余算
vdivu.vv vd, vs2, vs1, vm vdivu.vx vd, vs2, rs1, vm vdiv.vv vd, vs2, vs1, vm vdiv.vx vd, vs2, rs1, vm vremu.vv vd, vs2, vs1, vm vremu.vx vd, vs2, rs1, vm vrem.vv vd, vs2, vs1, vm vrem.vx vd, vs2, rs1, vm
ソフトウェアでやるより命令があったほうがまし程度の意味合い。
拡幅乗算
等幅×等幅→倍幅
vwmul.vv vd, vs2, vs1, vm vwmul.vx vd, vs2, rs1, vm vwmulu.vv vd, vs2, vs1, vm vwmulu.vx vd, vs2, rs1, vm vwmulsu.vv vd, vs2, vs1, vm vwmulsu.vx vd, vs2, rs1, vm
積和演算
vmacc.vv vd, vs1, vs2, vm # vd[i] = +(vs1[i] * vs2[i]) + vd[i] vmacc.vx vd, rs1, vs2, vm # vd[i] = +(x[rs1] * vs2[i]) + vd[i] vnmsac.vv vd, vs1, vs2, vm # vd[i] = -(vs1[i] * vs2[i]) + vd[i] vnmsac.vx vd, rs1, vs2, vm # vd[i] = -(x[rs1] * vs2[i]) + vd[i] vmadd.vv vd, vs1, vs2, vm # vd[i] = (vs1[i] * vd[i]) + vs2[i] vmadd.vx vd, rs1, vs2, vm # vd[i] = (x[rs1] * vd[i]) + vs2[i] vnmsub.vv vd, vs1, vs2, vm # vd[i] = -(vs1[i] * vd[i]) + vs2[i] vnmsub.vx vd, rs1, vs2, vm # vd[i] = -(x[rs1] * vd[i]) + vs2[i]
積和演算は4オペランド命令ではなくvdを読み書きする
なんでか分からないけどアセンブリのオペランドの順番が違う
拡幅積和演算
(等幅×等幅)+倍幅→倍幅
vwmaccu.vv vd, vs1, vs2, vm # vd[i] = +(vs1[i] * vs2[i]) + vd[i] vwmaccu.vx vd, rs1, vs2, vm # vd[i] = +(x[rs1] * vs2[i]) + vd[i] vwmacc.vv vd, vs1, vs2, vm # vd[i] = +(vs1[i] * vs2[i]) + vd[i] vwmacc.vx vd, rs1, vs2, vm # vd[i] = +(x[rs1] * vs2[i]) + vd[i] vwmaccsu.vv vd, vs1, vs2, vm # vd[i] = +(signed(vs1[i]) * unsigned(vs2[i])) + vd[i] vwmaccsu.vx vd, rs1, vs2, vm # vd[i] = +(signed(x[rs1]) * unsigned(vs2[i])) + vd[i] vwmaccus.vx vd, rs1, vs2, vm # vd[i] = +(unsigned(x[rs1]) * signed(vs2[i])) + vd[i]
Merge命令
俗にいうConditional move。v0が条件選択。
vmerge.vvm vd, vs2, vs1, v0 vmerge.vxm vd, vs2, rs1, v0 vmerge.vim vd, vs2, imm, v0
レジスタ転送
マスクはないけどvlは関係あるのでリネームだけでは終わらない。
vmv.vv vd, vs1 vmv.vx vd, rs1 vmv.vi vd, imm
エイリアス命令だとtail-agnosticで値が壊れるため別命令として存在している
固定小数演算
vxsatで飽和するか決めれる。丸めは浮動小数レジスタのfrmを参照して動的丸めモードで行う。
固定少数とは言ってるけど便利命令程度。
飽和加減算
飽和したら最も近い表現可能な値にしてvxsatがセットされる。
vsaddu.vv vd, vs2, vs1, vm vsaddu.vx vd, vs2, rs1, vm vsaddu.vi vd, vs2, imm, vm vsadd.vv vd, vs2, vs1, vm vsadd.vx vd, vs2, rs1, vm vsadd.vi vd, vs2, imm, vm vssubu.vv vd, vs2, vs1, vm vssubu.vx vd, vs2, rs1, vm vssub.vv vd, vs2, vs1, vm vssub.vx vd, vs2, rs1, vm
平均加減算
加減算して1bitシフトしてxvrmに従って丸める。vasub vasubuのオーバーフローは無視される。
vaaddu.vv vd, vs2, vs1, vm vaaddu.vx vd, vs2, rs1, vm vaadd.vv vd, vs2, vs1, vm vaadd.vx vd, vs2, rs1, vm vasubu.vv vd, vs2, vs1, vm vasubu.vx vd, vs2, rs1, vm vasub.vv vd, vs2, vs1, vm vasub.vx vd, vs2, rs1, vm
丸めと飽和付きの分数乗算
乗算(単幅×単幅→倍幅)→シフト&丸め&飽和→単幅
vsmul.vv vd, vs2, vs1, vm vsmul.vx vd, vs2, rs1, vm
Scaling シフト
右シフトしてvxrmに従って丸める。
vssrl.vv vd, vs2, vs1, vm vssrl.vx vd, vs2, rs1, vm vssrl.vi vd, vs2, uimm, vm vssra.vv vd, vs2, vs1, vm vssra.vx vd, vs2, rs1, vm vssra.vi vd, vs2, uimm, vm
Narrowing Fixed-Point Clip
倍幅>>等幅→丸め→等幅
vnclipu.wv vd, vs2, vs1, vm vnclipu.wx vd, vs2, rs1, vm vnclipu.wi vd, vs2, uimm, vm vnclip.wv vd, vs2, vs1, vm vnclip.wx vd, vs2, rs1, vm vnclip.wi vd, vs2, uimm, vm
浮動小数演算
標準ではIEEE754-2008のfp32とfp64だけ
fp16はZvfh拡張
例外fflagsとかの特権命令まわりはF D拡張と同じ
丸めは浮動小数レジスタのfrmを参照して動的丸めモードで行う。
加減算
vfadd.vv vd, vs2, vs1, vm vfadd.vf vd, vs2, rs1, vm vfsub.vv vd, vs2, vs1, vm vfsub.vf vd, vs2, rs1, vm vfrsub.vf vd, vs2, rs1, vm
拡幅加減算
等幅±等幅→倍幅
vfwadd.vv vd、vs2、vs1、vm vfwadd.vf vd、vs2、rs1、vm vfwsub.vv vd、vs2、vs1、vm vfwsub.vf vd、vs2、rs1、vm vfwadd.wv vd、vs2、vs1、vm vfwadd.wf vd、vs2、rs1、vm vfwsub.wv vd、vs2、vs1、vm vfwsub.wf vd、vs2、rs1、vm
乗算除算
vfmul.vv vd, vs2, vs1, vm vfmul.vf vd, vs2, rs1, vm vfdiv.vv vd, vs2, vs1, vm vfdiv.vf vd, vs2, rs1, vm # vd[i] = vs2[i] / f[rs1] vfrdiv.vf vd, vs2, rs1, vm # vd[i] = f[rs1] / vs2[i]
拡幅乗算
等幅×等幅→倍幅
vfwmul.vv vd, vs2, vs1, vm vfwmul.vf vd, vs2, rs1, vm
積和演算
vfmacc.vv vd, vs1, vs2, vm # vd[i] = +(vs1[i] * vs2[i]) + vd[i] vfmacc.vf vd, rs1, vs2, vm # vd[i] = +(f[rs1] * vs2[i]) + vd[i] vfnmacc.vv vd, vs1, vs2, vm # vd[i] = -(vs1[i] * vs2[i]) - vd[i] vfnmacc.vf vd, rs1, vs2, vm # vd[i] = -(f[rs1] * vs2[i]) - vd[i] vfmsac.vv vd, vs1, vs2, vm # vd[i] = +(vs1[i] * vs2[i]) - vd[i] vfmsac.vf vd, rs1, vs2, vm # vd[i] = +(f[rs1] * vs2[i]) - vd[i] vfnmsac.vv vd, vs1, vs2, vm # vd[i] = -(vs1[i] * vs2[i]) + vd[i] vfnmsac.vf vd, rs1, vs2, vm # vd[i] = -(f[rs1] * vs2[i]) + vd[i] vfmadd.vv vd, vs1, vs2, vm # vd[i] = +(vs1[i] * vd[i]) + vs2[i] vfmadd.vf vd, rs1, vs2, vm # vd[i] = +(f[rs1] * vd[i]) + vs2[i] vfnmadd.vv vd, vs1, vs2, vm # vd[i] = -(vs1[i] * vd[i]) - vs2[i] vfnmadd.vf vd, rs1, vs2, vm # vd[i] = -(f[rs1] * vd[i]) - vs2[i] vfmsub.vv vd, vs1, vs2, vm # vd[i] = +(vs1[i] * vd[i]) - vs2[i] vfmsub.vf vd, rs1, vs2, vm # vd[i] = +(f[rs1] * vd[i]) - vs2[i] vfnmsub.vv vd, vs1, vs2, vm # vd[i] = -(vs1[i] * vd[i]) + vs2[i] vfnmsub.vf vd, rs1, vs2, vm # vd[i] = -(f[rs1] * vd[i]) + vs2[i]
4オペランドではなく3オペランド命令なのでvdを読み書きする
拡幅積和演算
±(等幅×等幅)±倍幅→倍幅
vfwmacc.vv vd, vs1, vs2, vm # vd[i] = +(vs1[i] * vs2[i]) + vd[i] vfwmacc.vf vd, rs1, vs2, vm # vd[i] = +(f[rs1] * vs2[i]) + vd[i] vfwnmacc.vv vd, vs1, vs2, vm # vd[i] = -(vs1[i] * vs2[i]) - vd[i] vfwnmacc.vf vd, rs1, vs2, vm # vd[i] = -(f[rs1] * vs2[i]) - vd[i] vfwmsac.vv vd, vs1, vs2, vm # vd[i] = +(vs1[i] * vs2[i]) - vd[i] vfwmsac.vf vd, rs1, vs2, vm # vd[i] = +(f[rs1] * vs2[i]) - vd[i] vfwnmsac.vv vd, vs1, vs2, vm # vd[i] = -(vs1[i] * vs2[i]) + vd[i] vfwnmsac.vf vd, rs1, vs2, vm # vd[i] = -(f[rs1] * vs2[i]) + vd[i]
平方根
vfsqrt.v vd, vs2, vm
近似平方根/逆数
近似は7bitでいいらしいのでテーブル引き
vfrsqrt7.v vd, vs2, vm vfrec7.v vd, vs2, vm
近似精度はニュートン・ラプソン法を0,1,2,3回実行すればbf16(e8m7) fp16(e5m10) fp32(e8m23) fp64(e11m52)になるかららしい
min/max
vfmin.vv vd, vs2, vs1, vm vfmin.vf vd, vs2, rs1, vm vfmax.vv vd, vs2, vs1, vm vfmax.vf vd, vs2, rs1, vm
符号注入
negateとかabsoluteにつかえる
vfsgnj.vv vd, vs2, vs1, vm vfsgnj.vf vd, vs2, rs1, vm vfsgnjn.vv vd, vs2, vs1, vm vfsgnjn.vf vd, vs2, rs1, vm vfsgnjx.vv vd, vs2, vs1, vm vfsgnjx.vf vd, vs2, rs1, vm
比較
vmfeq.vv vd, vs2, vs1, vm vmfeq.vf vd, vs2, rs1, vm vmfne.vv vd, vs2, vs1, vm vmfne.vf vd, vs2, rs1, vm vmflt.vv vd, vs2, vs1, vm vmflt.vf vd, vs2, rs1, vm vmfle.vv vd, vs2, vs1, vm vmfle.vf vd, vs2, rs1, vm vmfgt.vf vd, vs2, rs1, vm vmfge.vf vd, vs2, rs1, vm
分類分け
F D 拡張と同じ
vfclass.v vd, vs2, vm
Merge命令
浮動小数レジスタから読み出すCMOV (整数レジスタはvmerge.vxm)
vfmerge.vfm vd, vs2, rs1, v0
転送命令
浮動小数レジスタからの転送。命令エンコードがvfmerge.vfmと同じ。vm=1かつvs2=v0の時にvfmv.v.f
vfmv.v.f vd, rs1
型変換
vfcvt.xu.f.v vd, vs2, vm vfcvt.x.f.v vd, vs2, vm vfcvt.rtz.xu.f.v vd, vs2, vm vfcvt.rtz.x.f.v vd, vs2, vm vfcvt.f.xu.v vd, vs2, vm vfcvt.f.x.v vd, vs2, vm
拡幅型変換
単幅→倍幅
vfwcvt.xu.f.v vd, vs2, vm vfwcvt.x.f.v vd, vs2, vm vfwcvt.rtz.xu.f.v vd, vs2, vm vfwcvt.rtz.x.f.v vd, vs2, vm vfwcvt.f.xu.v vd, vs2, vm vfwcvt.f.x.v vd, vs2, vm vfwcvt.f.f.v vd, vs2, vm
狭幅型変換
倍幅→単幅
vfncvt.xu.f.w vd, vs2, vm vfncvt.x.f.w vd, vs2, vm vfncvt.rtz.xu.f.w vd, vs2, vm vfncvt.rtz.x.f.w vd, vs2, vm vfncvt.f.xu.w vd, vs2, vm vfncvt.f.x.w vd, vs2, vm vfncvt.f.f.w vd, vs2, vm vfncvt.rod.f.f.w vd, vs2, vm
縮約演算
vs2の全要素とvs1[0]との縮約をvd[0]に書き込む
単幅整数縮約
vredsum.vs vd, vs2, vs1, vm vredmaxu.vs vd, vs2, vs1, vm vredmax.vs vd, vs2, vs1, vm vredminu.vs vd, vs2, vs1, vm vredmin.vs vd, vs2, vs1, vm vredand.vs vd, vs2, vs1, vm vredor.vs vd, vs2, vs1, vm vredxor.vs vd, vs2, vs1, vm
拡幅整数縮約
sum(単幅)→倍幅
vwredsumu.vs vd, vs2, vs1, vm vwredsum.vs vd, vs2, vs1, vm
浮動小数縮約
vfredosum.vs vd, vs2, vs1, vm vfredusum.vs vd, vs2, vs1, vm vfredmax.vs vd, vs2, vs1, vm vfredmin.vs vd, vs2, vs1, vm
演算過程は有限精度なため、順序ありorderedとなしunordered命令がある。
拡幅浮動小数縮約
sum(単幅)→倍幅
vfwredosum.vs vd, vs2, vs1, vm vfwredusum.vs vd, vs2, vs1, vm
マスク演算
マスク論理演算
vmand.mm vd, vs2, vs1 vmnand.mm vd, vs2, vs1 vmandn.mm vd, vs2, vs1 vmxor.mm vd, vs2, vs1 vmor.mm vd, vs2, vs1 vmnor.mm vd, vs2, vs1 vmorn.mm vd, vs2, vs1 vmxnor.mm vd, vs2, vs1
count population
マスクが立ってるエレメント数を数える
vcpop.m rd, vs2, vm
ベクトルレジスタに書き込みを行わず、整数レジスタに転送する。再開はできるわけないのでvstartは常に0
find-first-set mask bit
マスクに1が立っている最初のエレメントの位置を返す
vfirst.m rd, vs2, vm
ベクトルレジスタに書き込みを行わず、整数レジスタに転送する。再開はできるわけないのでvstartは常に0
set-before-first/set-including-first/set-only-first
マスクに1が立っている最初のエレメントの位置を探して{以前, 以後, その場所}に1を立てる
vmsbf.m vd, vs2, vm vmsif.m vd, vs2, vm vmsof.m vd, vs2, vm
文字列比較(ヌル文字)&コピーとかに使う。再開はできるわけないのでvstartは常に0
Iota命令
自分の位置より前のマスクの有効な数を数える
viota.m vd, vs2, vm
再開はできるわけないのでvstartは常に0
Element Index
エレメントの場所
vid.v vd, vm
並べ替え命令
スカラ転送命令
マスクとvlに関係なく実行される。vm=0は予約命令。
整数レジスタとベクトルレジスタの0番目の要素の転送
vmv.x.s rd, vs2 vmv.s.x vd, rs1
浮動小数レジスタとベクトルレジスタの0番目の要素の転送。
vfmv.f.s rd, vs2 vfmv.s.f vd, rs1
スライド命令
vslideup.vx vd, vs2, rs1, vm vslideup.vi vd, vs2, uimm, vm vslidedown.vx vd, vs2, rs1, vm vslidedown.vi vd, vs2, uimm, vm
再開を実現するためにvd != vs2でなくてはいけない
Slide1up/down
整数レジスタor浮動小数レジスタから読み込んで1個ずつずらす
vslide1up.vx vd, vs2, rs1, vm vfslide1up.vf vd, vs2, rs1, vm vslide1down.vx vd, vs2, rs1, vm vfslide1down.vf vd, vs2, rs1, vm
Gather命令
vd[i] = (vs1[i] >= VLMAX) ? 0 : vs2[vs1[i]]
vrgather.vv vd, vs2、vs1, vm vrgatherei16.vv vd, vs2, vs1, vm
SEW=8のときはvs1が0~255までしか指定できないのでvrgatheri16.vvはレジスタグループで64Kまで指定できるようにしている
再開を実現するためにvd != vs2でなくてはいけない
vrgather.vx vd, vs2, rs1, vm vrgather.vi vd, vs2, uimm, vm
ただのブロードキャスト。再開を実現するためにvd != vs2でなくてはいけない
圧縮命令
vs1が有効な値(非ゼロ)の位置のvs2の値を先頭から詰める。
vcompress.vm vd, vs2, vs1
途中で再開が難しいため、vstart != 0なら不正命令例外。マスク命令vm=0は存在せず、予約済み。
ベクトルレジスタ全体転送命令
レジスタグループにして全転送。マスクもtailも関係ないので、リネーミングだけで済ませても良い。
vmv<nr>r.v vd, vs2
<nr>={1,2,4,8}




