算术指令¶
向量算术指令使用单独 opcode:OP-V=1010111 ,指令格式如下所示:
| funct6[5:0] | vm | rs2[4:0] | rs1[4:0] | funct3[2:0] | rd[4:0] | opcode[6:0] | |
|---|---|---|---|---|---|---|---|
| funct6 | vm | vs2 | vs1 | 000 | vd | 1010111 | OPIVV |
| funct6 | vm | vs2 | vs1 | 001 | vd/sd | 1010111 | OPFVV |
| funct6 | vm | vs2 | vs1 | 010 | vd/sd | 1010111 | OPMVV |
| funct6 | vm | vs2 | simm5 | 011 | vd | 1010111 | OPIVI |
| funct6 | vm | vs2 | ss1 | 100 | vd | 1010111 | OPIVS |
| funct6 | vm | vs2 | ss1 | 101 | vd | 1010111 | OPFVS |
| funct6 | vm | vs2 | ss1 | 110 | vd | 1010111 | OPMVS |
其中:
funct3域用来定义指令的子类,包括操作数的类型和来源:
| funct3[2:0] | 指令类型 | 操作类型 | 操作数来源 |
|---|---|---|---|
| 000 | OPIVV | 整数 | 向量寄存器-向量寄存器 |
| 001 | OPFVV | 浮点数 | 向量寄存器-向量寄存器 |
| 010 | OPMVV | 整数 | 向量寄存器-向量寄存器 |
| 011 | OPIVI | 整数 | 向量寄存器-立即数 |
| 100 | OPIVS | 整数 | 向量寄存器-共享寄存器 |
| 101 | OPFVS | 浮点数 | 向量寄存器-共享寄存器 |
| 110 | OPMVS | 整数 | 向量寄存器-共享寄存器 |
指令中的操作数来源寄存器(向量寄存器/共享寄存器)根据funct3域确定。注意其中操作数2(vs2)总是向量寄存器。
funct6域用来指定计算类型,其与funct3共同编码算术指令类型。详细编码表见附表。vm域为 0 的时候表示该指令仅在vv0对应元素的 LSB 为 1 时生效
以下列出基本的算术指令。考虑初步实现的简化,暂时略去诸多指令。注意,略去的指令编码也在附表中给出。
整数算术指令¶
整数算术指令目前仅考虑单宽度的基本整数算术指令,暂时不考虑整数乘除法指令等。
整数加减法指令¶
整数加减(反减)法指令:
# Integer add
vadd.vv vd, vs2, vs1, vm # Vector-vector, vd[i] = vs2[i] + vs1[i]
vadd.vs vd, vs2, ss1, vm # vector-scalar, vd[i] = vs2[i] + ss1
vadd.vi vd, vs2, imm, vm # vector-immediate, vd[i] = vs2[i] + imm
# Integer subtract
vsub.vv vd, vs2, vs1, vm # Vector-vector, vd[i] = vs2[i] - vs1[i]
vsub.vs vd, vs2, ss1, vm # vector-scalar, vd[i] = vs2[i] - ss1
# Integer reverse subtract
vrsub.vs vd, vs2, ss1, vm # vd[i] = ss1 - vs2[i]
vrsub.vi vd, vs2, imm, vm # vd[i] = imm - vs2[i]
整数按位逻辑指令¶
整数按位与、或、异或指令:
# Bitwise logical operations.
vand.vv vd, vs2, vs1, vm # Vector-vector, vd[i] = vs2[i] & vs1[i]
vand.vs vd, vs2, ss1, vm # vector-scalar, vd[i] = vs2[i] & ss1
vand.vi vd, vs2, imm, vm # vector-immediate, vd[i] = vs2[i] & imm
vor.vv vd, vs2, vs1, vm # Vector-vector, vd[i] = vs2[i] | vs1[i]
vor.vs vd, vs2, ss1, vm # vector-scalar, vd[i] = vs2[i] | ss1
vor.vi vd, vs2, imm, vm # vector-immediate, vd[i] = vs2[i] | imm
vxor.vv vd, vs2, vs1, vm # Vector-vector, vd[i] = vs2[i] ^ vs1[i]
vxor.vs vd, vs2, ss1, vm # vector-scalar, vd[i] = vs2[i] ^ ss1
vxor.vi vd, vs2, imm, vm # vector-immediate, vd[i] = vs2[i] ^ imm
其中将向量-立即数的 VXOR.VI 指令中的立即数设置为 -1 可以实现按位 NOT 操作,可以提供伪汇编指令 vnot.v。
整数移位指令¶
整数移位指令:
# Bit shift operations
vsll.vv vd, vs2, vs1, vm # Vector-vector, vd[i] = vs2[i] << vs1[i](lg2(SEW)-1, 0)
vsll.vs vd, vs2, ss1, vm # vector-scalar, vd[i] = vs2[i] << ss1(lg2(SEW)-1, 0)
vsll.vi vd, vs2, uimm, vm # vector-immediate, vd[i] = vs2[i] << uimm(lg2(SEW)-1, 0)
vsrl.vv vd, vs2, vs1, vm # Vector-vector, vd[i] = vs2[i] >> vs1[i](lg2(SEW)-1, 0)
vsrl.vs vd, vs2, ss1, vm # vector-scalar, vd[i] = vs2[i] >> ss1(lg2(SEW)-1, 0)
vsrl.vi vd, vs2, uimm, vm # vector-immediate, vd[i] = vs2[i] >> uimm(lg2(SEW)-1, 0)
vsra.vv vd, vs2, vs1, vm # Vector-vector, vd[i] = signed(vs2[i]) >> vs1[i](lg2(SEW)-1, 0)
vsra.vs vd, vs2, ss1, vm # vector-scalar, vd[i] = signed(vs2[i]) >> ss1(lg2(SEW)-1, 0)
vsra.vi vd, vs2, uimm, vm # vector-immediate, vd[i] = signed(vs2[i]) >> uimm(lg2(SEW)-1, 0)
其中立即数均按照无符号数处理(uimm = unsigned imm)。寄存器值中的低 lg2(SEW) 位被取出作为移位量。
整数比较指令¶
整数比较指令的结果写入结果寄存器的 LSB 中,即结果寄存器作为向量 mask 寄存器使用:
# Set if equal
vmseq.vv vd, vs2, vs1, vm # Vector-vector, vd[i] = vs2[i] == vs[i]
vmseq.vs vd, vs2, ss1, vm # vector-scalar, vd[i] = vs2[i] == ss1
vmseq.vi vd, vs2, imm, vm # vector-immediate, vd[i] = vs2[i] == imm
# Set if not equal
vmsne.vv vd, vs2, vs1, vm # Vector-vector, vd[i] = vs2[i] != vs[1]
vmsne.vs vd, vs2, ss1, vm # vector-scalar, vd[i] = vs2[i] != ss1
vmsne.vi vd, vs2, imm, vm # vector-immediate, vd[i] = vs2[i] != imm
# Set if less than, unsigned
vmsltu.vv vd, vs2, vs1, vm # Vector-vector, vd[i] = vs2[i] < vs[1]
vmsltu.vs vd, vs2, ss1, vm # Vector-scalar, vd[i] = vs2[i] < ss1
# Set if less than, signed
vmslt.vv vd, vs2, vs1, vm # Vector-vector, vd[i] = signed(vs2[i]) < signed(vs[1])
vmslt.vs vd, vs2, ss1, vm # vector-scalar, vd[i] = signed(vs2[i]) < signed(ss1)
# Set if less than or equal, unsigned
vmsleu.vv vd, vs2, vs1, vm # Vector-vector, vd[i] = vs2[i] <= vs[1]
vmsleu.vs vd, vs2, ss1, vm # vector-scalar, vd[i] = vs2[i] <= ss1
vmsleu.vi vd, vs2, uimm, vm # Vector-immediate, vd[i] = vs2[i] <= uimm
# Set if less than or equal, signed
vmsle.vv vd, vs2, vs1, vm # Vector-vector, vd[i] = signed(vs2[i]) <= signed(vs[1])
vmsle.vs vd, vs2, ss1, vm # vector-scalar, vd[i] = signed(vs2[i]) <= signed(ss1)
vmsle.vi vd, vs2, imm, vm # vector-immediate, vd[i] = signed(vs2[i]) <= imm
# Set if greater than, unsigned
vmsgtu.vs vd, vs2, ss1, vm # Vector-scalar, vd[i] = vs2[i] > ss1
vmsgtu.vi vd, vs2, uimm, vm # Vector-immediate, vd[i] = vs2[i] > uimm
# Set if greater than, signed
vmsgt.vs vd, vs2, ss1, vm # Vector-scalar, vd[i] = signed(vs2[i]) > signed(ss1)
vmsgt.vi vd, vs2, imm, vm # Vector-immediate, vd[i] = signed(vs2[i]) > imm
未列出的指令变种作为伪汇编指令实现。
Warning
TODO:补充伪汇编指令映射实现。
浮点算术指令¶
浮点算术指令同样暂时只考虑单宽度的基本浮点算术指令。
浮点加减法指令¶
浮点加减法指令:
# Floating-point add
vfadd.vv vd, vs2, vs1, vm # Vector-vector vd[i] = vs2[i] + vs1[i]
vfadd.vs vd, vs2, ss1, vm # vector-scalar vd[i] = vs2[i] + ss1
# Floating-point subtract
vfsub.vv vd, vs2, vs1, vm # Vector-vector vd[i] = vs2[i] - vs1[i]
vfsub.vs vd, vs2, ss1, vm # Vector-scalar vd[i] = vs2[i] - ss1
vfrsub.vs vd, vs2, ss1, vm # Scalar-vector vd[i] = ss1 - vs2[i]
浮点乘除法指令¶
浮点乘除法指令:
# Floating-point multiply
vfmul.vv vd, vs2, vs1, vm # Vector-vector vd[i] = vs2[i] * vs1[i]
vfmul.vs vd, vs2, ss1, vm # vector-scalar vd[i] = vs2[i] * ss1
# Floating-point divide
vfdiv.vv vd, vs2, vs1, vm # Vector-vector vd[i] = vs2[i] / vs1[i]
vfdiv.vs vd, vs2, ss1, vm # vector-scalar vd[i] = vs2[i] / ss1
# Reverse floating-point divide vector = scalar / vector
vfrdiv.vs vd, vs2, ss1, vm # scalar-vector, vd[i] = ss1 / vs2[i]
浮点乘加指令¶
浮点乘加指令包含四种乘加操作的各两个变种(结果覆盖加数/第一个乘数):
# FP multiply-accumulate, overwrites addend
vfmacc.vv vd, vs1, vs2, vm # vd[i] = +(vs1[i] * vs2[i]) + vd[i]
vfmacc.vs vd, ss1, vs2, vm # vd[i] = +(s[ss1] * vs2[i]) + vd[i]
# FP negate-(multiply-accumulate), overwrites subtrahend
vfnmacc.vv vd, vs1, vs2, vm # vd[i] = -(vs1[i] * vs2[i]) - vd[i]
vfnmacc.vs vd, ss1, vs2, vm # vd[i] = -(s[ss1] * vs2[i]) - vd[i]
# FP multiply-subtract-accumulator, overwrites subtrahend
vfmsac.vv vd, vs1, vs2, vm # vd[i] = +(vs1[i] * vs2[i]) - vd[i]
vfmsac.vs vd, ss1, vs2, vm # vd[i] = +(s[ss1] * vs2[i]) - vd[i]
# FP negate-(multiply-subtract-accumulator), overwrites minuend
vfnmsac.vv vd, vs1, vs2, vm # vd[i] = -(vs1[i] * vs2[i]) + vd[i]
vfnmsac.vs vd, ss1, vs2, vm # vd[i] = -(s[ss1] * vs2[i]) + vd[i]
# FP multiply-add, overwrites multiplicand
vfmadd.vv vd, vs1, vs2, vm # vd[i] = +(vs1[i] * vd[i]) + vs2[i]
vfmadd.vs vd, ss1, vs2, vm # vd[i] = +(s[ss1] * vd[i]) + vs2[i]
# FP negate-(multiply-add), overwrites multiplicand
vfnmadd.vv vd, vs1, vs2, vm # vd[i] = -(vs1[i] * vd[i]) - vs2[i]
vfnmadd.vs vd, rs1, vs2, vm # vd[i] = -(s[ss1] * vd[i]) - vs2[i]
# FP multiply-sub, overwrites multiplicand
vfmsub.vv vd, vs1, vs2, vm # vd[i] = +(vs1[i] * vd[i]) - vs2[i]
vfmsub.vs vd, ss1, vs2, vm # vd[i] = +(s[ss1] * vd[i]) - vs2[i]
# FP negate-(multiply-sub), overwrites multiplicand
vfnmsub.vv vd, vs1, vs2, vm # vd[i] = -(vs1[i] * vd[i]) + vs2[i]
vfnmsub.vs vd, ss1, vs2, vm # vd[i] = -(s[ss1] * vd[i]) + vs2[i]
附表:算术指令功能码表¶
| funct6 | OPIVV | OPIVS | OPIVI | OPMVV | OPMVS | OPFVV | OPFVS |
|---|---|---|---|---|---|---|---|
| 000000 | vadd.vv | vadd.vs | vadd.vi | vredsum.vs | vfadd.vv | vfadd.vs | |
| 000001 | vredand.vs | vfredsum.vs | |||||
| 000010 | vsub.vv | vsub.vs | vredor.vs | vfsub.vv | vfsub.vs | ||
| 000011 | vrsub.vs | vrsub.vi | vredxor.vs | vfredosum.vs | |||
| 000100 | vminu.vv | vminu.vs | vredminu.vs | vfmin.vv | vfmin.vs | ||
| 000101 | vmin.vv | vmin.vs | vredmin.vs | vfredmin.vs | |||
| 000110 | vmaxu.vv | vmaxu.vs | vredmaxu.vs | vfmax.vv | vfmax.vs | ||
| 000111 | vmax.vv | vmax.vs | vredmax.vs | vfredmax.vs | |||
| 001000 | vaaddu.vv | vaaddu.vs | vfsgnj.vv | vfsgnj.vs | |||
| 001001 | vand.vv | vand.vs | vand.vi | vaadd.vv | vaadd.vs | vfsgnjn.vv | vfsgnjn.vs |
| 001010 | vor.vv | vor.vs | vor.vi | vasubu.vv | vasubu.vs | vfsgnjx.vv | vfsgnjx.vs |
| 001011 | vxor.vv | vxor.vs | vxor.vi | vasub.vv | vasub.vs | ||
| 001100 | vrgather.vv | vrgather.vs | vrgather.vi | ||||
| 001101 | |||||||
| 001110 | vslideup.vs | vslideup.vi | vslide1up.vs | ||||
| 001111 | vslidedown.vs | vslidedown.vi | vslide1down.vs | ||||
| 010000 | vadc.vvm | vadc.vsm | vadc.vim | VWXUNARY0 | VRX-UNARY0 | VWFUNARY0 | VRF-UNARY0 |
| 010001 | vmadc.vvm | vmadc.vsm | vmadc.vim | ||||
| 010010 | vsbc.vvm | vsbc.vsm | vsbc.vim | ||||
| 010011 | vmsbc.vvm | vmsbc.vsm | vmsbc.vim | ||||
| 010100 | VMUNARY0 | ||||||
| 010101 | |||||||
| 010110 | |||||||
| 010111 | vmerge.vxm vmv.v.v |
vmerge.vsm vmv.v.s |
vmerge.vim vmv.v.i |
vcompress.vm | vmerge.vsm vfmv.v.s |
||
| 011000 | vmseq.vv | vmseq.vs | vmseq.vi | vmandnot.mm | vmfeq.vv | vmfeq.vs | |
| 011001 | vmsne.vv | vmsne.vs | vmsne.vi | vmand.mm | vmfle.vv | vmfle.vs | |
| 011010 | vmsltu.vv | vmsltu.vs | vmor.mm | ||||
| 011011 | vmslt.vv | vmslt.vs | vmxor.mm | vmflt.vv | vmflt.vs | ||
| 011100 | vmsleu.vv | vmsleu.vs | vmsleu.vi | vmornot.mm | vmfne.vv | vmfne.vs | |
| 011101 | vmsle.vv | vmsle.vs | vmsle.vi | vmnand.mm | vmfgt.vs | ||
| 011110 | vmsgtu.vs | vmsgtu.vi | vmnor.mm | ||||
| 011111 | vmsgt.vs | vmsgt.vi | vmxnor.mm | vmfge.vs | |||
| 100000 | vsaddu.vv | vsaddu.vs | vsaddu.vi | vdivu.vv | vdivu.vs | vfdiv.vv | vfdiv.vs |
| 100001 | vsadd.vv | vsadd.vs | vsadd.vi | vdiv.vv | vdiv.vs | vfrdiv.vs | |
| 100010 | vssubu.vv | vssubu.vs | vremu.vv | vremu.vs | VFUNARY0 | ||
| 100011 | vssub.vv | vssub.vs | vrem.vv | vrem.vs | VFUNARY1 | ||
| 100100 | vmulhu.vv | vmulhu.vs | vfmul.vv | vfmul.vs | |||
| 100101 | vsll.vv | vsll.vs | vsll.vi | vmul.vv | vmul.vs | ||
| 100110 | vmulhsu.vv | vmulhsu.vs | |||||
| 100111 | vsmul.vv | vsmul.vs | vmv<nf>r.v | vmulh.vv | vmulh.vs | vfrsub.vs | |
| 101000 | vsrl.vv | vsrl.vs | vsrl.vi | vfmadd.vv | vfmadd.vs | ||
| 101001 | vsra.vv | vra.vs | vsra.vi | vmadd.vv | vmadd.vs | vfnmadd.vv | vfnmadd.vs |
| 101010 | vssrl.vv | vssrl.vs | vssrl.vi | vfmsub.vv | vfmsub.vs | ||
| 101011 | vssra.vv | vssra.vs | vssra.vi | vnmsub.vv | vnmsub.vs | vfnmsub.vv | vfnmsub.vs |
| 101100 | vnsrl.vv | vnsrl.vs | vnsrl.vi | vfmacc.vv | vfmacc.vs | ||
| 101101 | vnsra.vv | vnsra.vs | vnsra.vi | vmacc.vv | vmacc.vs | vfnmacc.vv | vfnmacc.vs |
| 101110 | vnclipu.vv | vnclipu.vs | vnclipu.vi | vfmsac.vv | vfmsac.vs | ||
| 101111 | vnclip.vv | vnclip.vs | vnclip.vi | vnmsac.vv | vnmsac.vs | vfnmsac.vv | vfnmsac.vs |
| 110000 | vwredsumu.vs | vwaddu.vv | vwaddu.vs | vfwadd.vv | vfwadd.vs | ||
| 110001 | vwred-vsum.vs | vwadd.vv | vwadd.vs | vfwred-sum.vs | |||
| 110010 | vwsubu.vv | vwsubu.vs | vfwsub.vv | vfwsub.vs | |||
| 110011 | vwsub.vv | vwsub.vs | vfwredosum.vs | ||||
| 110100 | vwaddu.wv | vwaddu.ws | vfwadd.wv | vfwadd.ws | |||
| 110101 | vwadd.wv | vwadd.ws | |||||
| 110110 | vwsubu.wv | vwsubu.ws | vfwsub.wv | vfwsub.vs | |||
| 110111 | vwsub.wv | vwsub.ws | |||||
| 111000 | vdotu.vv | vwmulu.vv | vwmulu.vs | vfwmul.vv | vfwmul.vs | ||
| 111001 | vdot.vv | vfdot.vv | |||||
| 111010 | vwmulsu.vv | vwmulsu.vs | |||||
| 111011 | vwmul.vv | vwmul.vs | |||||
| 111100 | vqmaccu.vv | vqmaccu.vs | vwmaccu.vv | vwmaccu.vs | vfwmacc.vv | vfwmacc.vs | |
| 111101 | vqmacc.vv | vqmacc.vs | vwmacc.vv | vwmacc.vs | vfwnmacc.vv | vfwnmacc.vs | |
| 111110 | vqmaccus.vs | vwmaccus.vv | vwmaccus.vs | vfwmsac.vv | vfwmsac.vs | ||
| 111111 | vqmaccsu.vv | vqmaccsu.vs | vwmaccsu.vv | vwmaccsu.vs | vfwnmsac.vv | vfwnmsac.vs |
Warning
作为框架供参考。TODO:表格需要校对。
最后更新: April 9, 2020
作者: