mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-29 13:00:35 +00:00
bd550337f6
Older binutils versions do not include support for the vector instruction formats. Add assembler macros for vector instruction mnemonics to easily encode and generate vector instructions. Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
481 lines
9.4 KiB
C
481 lines
9.4 KiB
C
/*
|
|
* Support for Vector Instructions
|
|
*
|
|
* Assembler macros to generate .byte/.word code for particular
|
|
* vector instructions that are supported by recent binutils (>= 2.26) only.
|
|
*
|
|
* Copyright IBM Corp. 2015
|
|
* Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
|
|
*/
|
|
|
|
#ifndef __ASM_S390_VX_INSN_H
|
|
#define __ASM_S390_VX_INSN_H
|
|
|
|
#ifdef __ASSEMBLY__
|
|
|
|
|
|
/* Macros to generate vector instruction byte code */
|
|
|
|
#define REG_NUM_INVALID 255
|
|
|
|
/* GR_NUM - Retrieve general-purpose register number
|
|
*
|
|
* @opd: Operand to store register number
|
|
* @r64: String designation register in the format "%rN"
|
|
*/
|
|
.macro GR_NUM opd gr
|
|
\opd = REG_NUM_INVALID
|
|
.ifc \gr,%r0
|
|
\opd = 0
|
|
.endif
|
|
.ifc \gr,%r1
|
|
\opd = 1
|
|
.endif
|
|
.ifc \gr,%r2
|
|
\opd = 2
|
|
.endif
|
|
.ifc \gr,%r3
|
|
\opd = 3
|
|
.endif
|
|
.ifc \gr,%r4
|
|
\opd = 4
|
|
.endif
|
|
.ifc \gr,%r5
|
|
\opd = 5
|
|
.endif
|
|
.ifc \gr,%r6
|
|
\opd = 6
|
|
.endif
|
|
.ifc \gr,%r7
|
|
\opd = 7
|
|
.endif
|
|
.ifc \gr,%r8
|
|
\opd = 8
|
|
.endif
|
|
.ifc \gr,%r9
|
|
\opd = 9
|
|
.endif
|
|
.ifc \gr,%r10
|
|
\opd = 10
|
|
.endif
|
|
.ifc \gr,%r11
|
|
\opd = 11
|
|
.endif
|
|
.ifc \gr,%r12
|
|
\opd = 12
|
|
.endif
|
|
.ifc \gr,%r13
|
|
\opd = 13
|
|
.endif
|
|
.ifc \gr,%r14
|
|
\opd = 14
|
|
.endif
|
|
.ifc \gr,%r15
|
|
\opd = 15
|
|
.endif
|
|
.if \opd == REG_NUM_INVALID
|
|
.error "Invalid general-purpose register designation: \gr"
|
|
.endif
|
|
.endm
|
|
|
|
/* VX_R() - Macro to encode the VX_NUM into the instruction */
|
|
#define VX_R(v) (v & 0x0F)
|
|
|
|
/* VX_NUM - Retrieve vector register number
|
|
*
|
|
* @opd: Operand to store register number
|
|
* @vxr: String designation register in the format "%vN"
|
|
*
|
|
* The vector register number is used for as input number to the
|
|
* instruction and, as well as, to compute the RXB field of the
|
|
* instruction. To encode the particular vector register number,
|
|
* use the VX_R(v) macro to extract the instruction opcode.
|
|
*/
|
|
.macro VX_NUM opd vxr
|
|
\opd = REG_NUM_INVALID
|
|
.ifc \vxr,%v0
|
|
\opd = 0
|
|
.endif
|
|
.ifc \vxr,%v1
|
|
\opd = 1
|
|
.endif
|
|
.ifc \vxr,%v2
|
|
\opd = 2
|
|
.endif
|
|
.ifc \vxr,%v3
|
|
\opd = 3
|
|
.endif
|
|
.ifc \vxr,%v4
|
|
\opd = 4
|
|
.endif
|
|
.ifc \vxr,%v5
|
|
\opd = 5
|
|
.endif
|
|
.ifc \vxr,%v6
|
|
\opd = 6
|
|
.endif
|
|
.ifc \vxr,%v7
|
|
\opd = 7
|
|
.endif
|
|
.ifc \vxr,%v8
|
|
\opd = 8
|
|
.endif
|
|
.ifc \vxr,%v9
|
|
\opd = 9
|
|
.endif
|
|
.ifc \vxr,%v10
|
|
\opd = 10
|
|
.endif
|
|
.ifc \vxr,%v11
|
|
\opd = 11
|
|
.endif
|
|
.ifc \vxr,%v12
|
|
\opd = 12
|
|
.endif
|
|
.ifc \vxr,%v13
|
|
\opd = 13
|
|
.endif
|
|
.ifc \vxr,%v14
|
|
\opd = 14
|
|
.endif
|
|
.ifc \vxr,%v15
|
|
\opd = 15
|
|
.endif
|
|
.ifc \vxr,%v16
|
|
\opd = 16
|
|
.endif
|
|
.ifc \vxr,%v17
|
|
\opd = 17
|
|
.endif
|
|
.ifc \vxr,%v18
|
|
\opd = 18
|
|
.endif
|
|
.ifc \vxr,%v19
|
|
\opd = 19
|
|
.endif
|
|
.ifc \vxr,%v20
|
|
\opd = 20
|
|
.endif
|
|
.ifc \vxr,%v21
|
|
\opd = 21
|
|
.endif
|
|
.ifc \vxr,%v22
|
|
\opd = 22
|
|
.endif
|
|
.ifc \vxr,%v23
|
|
\opd = 23
|
|
.endif
|
|
.ifc \vxr,%v24
|
|
\opd = 24
|
|
.endif
|
|
.ifc \vxr,%v25
|
|
\opd = 25
|
|
.endif
|
|
.ifc \vxr,%v26
|
|
\opd = 26
|
|
.endif
|
|
.ifc \vxr,%v27
|
|
\opd = 27
|
|
.endif
|
|
.ifc \vxr,%v28
|
|
\opd = 28
|
|
.endif
|
|
.ifc \vxr,%v29
|
|
\opd = 29
|
|
.endif
|
|
.ifc \vxr,%v30
|
|
\opd = 30
|
|
.endif
|
|
.ifc \vxr,%v31
|
|
\opd = 31
|
|
.endif
|
|
.if \opd == REG_NUM_INVALID
|
|
.error "Invalid vector register designation: \vxr"
|
|
.endif
|
|
.endm
|
|
|
|
/* RXB - Compute most significant bit used vector registers
|
|
*
|
|
* @rxb: Operand to store computed RXB value
|
|
* @v1: First vector register designated operand
|
|
* @v2: Second vector register designated operand
|
|
* @v3: Third vector register designated operand
|
|
* @v4: Fourth vector register designated operand
|
|
*/
|
|
.macro RXB rxb v1 v2=0 v3=0 v4=0
|
|
\rxb = 0
|
|
.if \v1 & 0x10
|
|
\rxb = \rxb | 0x08
|
|
.endif
|
|
.if \v2 & 0x10
|
|
\rxb = \rxb | 0x04
|
|
.endif
|
|
.if \v3 & 0x10
|
|
\rxb = \rxb | 0x02
|
|
.endif
|
|
.if \v4 & 0x10
|
|
\rxb = \rxb | 0x01
|
|
.endif
|
|
.endm
|
|
|
|
/* MRXB - Generate Element Size Control and RXB value
|
|
*
|
|
* @m: Element size control
|
|
* @v1: First vector register designated operand (for RXB)
|
|
* @v2: Second vector register designated operand (for RXB)
|
|
* @v3: Third vector register designated operand (for RXB)
|
|
* @v4: Fourth vector register designated operand (for RXB)
|
|
*/
|
|
.macro MRXB m v1 v2=0 v3=0 v4=0
|
|
rxb = 0
|
|
RXB rxb, \v1, \v2, \v3, \v4
|
|
.byte (\m << 4) | rxb
|
|
.endm
|
|
|
|
/* MRXBOPC - Generate Element Size Control, RXB, and final Opcode fields
|
|
*
|
|
* @m: Element size control
|
|
* @opc: Opcode
|
|
* @v1: First vector register designated operand (for RXB)
|
|
* @v2: Second vector register designated operand (for RXB)
|
|
* @v3: Third vector register designated operand (for RXB)
|
|
* @v4: Fourth vector register designated operand (for RXB)
|
|
*/
|
|
.macro MRXBOPC m opc v1 v2=0 v3=0 v4=0
|
|
MRXB \m, \v1, \v2, \v3, \v4
|
|
.byte \opc
|
|
.endm
|
|
|
|
/* Vector support instructions */
|
|
|
|
/* VECTOR GENERATE BYTE MASK */
|
|
.macro VGBM vr imm2
|
|
VX_NUM v1, \vr
|
|
.word (0xE700 | (VX_R(v1) << 4))
|
|
.word \imm2
|
|
MRXBOPC 0, 0x44, v1
|
|
.endm
|
|
.macro VZERO vxr
|
|
VGBM \vxr, 0
|
|
.endm
|
|
.macro VONE vxr
|
|
VGBM \vxr, 0xFFFF
|
|
.endm
|
|
|
|
/* VECTOR LOAD VR ELEMENT FROM GR */
|
|
.macro VLVG v, gr, disp, m
|
|
VX_NUM v1, \v
|
|
GR_NUM b2, "%r0"
|
|
GR_NUM r3, \gr
|
|
.word 0xE700 | (VX_R(v1) << 4) | r3
|
|
.word (b2 << 12) | (\disp)
|
|
MRXBOPC \m, 0x22, v1
|
|
.endm
|
|
.macro VLVGB v, gr, index, base
|
|
VLVG \v, \gr, \index, \base, 0
|
|
.endm
|
|
.macro VLVGH v, gr, index
|
|
VLVG \v, \gr, \index, 1
|
|
.endm
|
|
.macro VLVGF v, gr, index
|
|
VLVG \v, \gr, \index, 2
|
|
.endm
|
|
.macro VLVGG v, gr, index
|
|
VLVG \v, \gr, \index, 3
|
|
.endm
|
|
|
|
/* VECTOR LOAD */
|
|
.macro VL v, disp, index="%r0", base
|
|
VX_NUM v1, \v
|
|
GR_NUM x2, \index
|
|
GR_NUM b2, \base
|
|
.word 0xE700 | (VX_R(v1) << 4) | x2
|
|
.word (b2 << 12) | (\disp)
|
|
MRXBOPC 0, 0x06, v1
|
|
.endm
|
|
|
|
/* VECTOR LOAD ELEMENT */
|
|
.macro VLEx vr1, disp, index="%r0", base, m3, opc
|
|
VX_NUM v1, \vr1
|
|
GR_NUM x2, \index
|
|
GR_NUM b2, \base
|
|
.word 0xE700 | (VX_R(v1) << 4) | x2
|
|
.word (b2 << 12) | (\disp)
|
|
MRXBOPC \m3, \opc, v1
|
|
.endm
|
|
.macro VLEB vr1, disp, index="%r0", base, m3
|
|
VLEx \vr1, \disp, \index, \base, \m3, 0x00
|
|
.endm
|
|
.macro VLEH vr1, disp, index="%r0", base, m3
|
|
VLEx \vr1, \disp, \index, \base, \m3, 0x01
|
|
.endm
|
|
.macro VLEF vr1, disp, index="%r0", base, m3
|
|
VLEx \vr1, \disp, \index, \base, \m3, 0x03
|
|
.endm
|
|
.macro VLEG vr1, disp, index="%r0", base, m3
|
|
VLEx \vr1, \disp, \index, \base, \m3, 0x02
|
|
.endm
|
|
|
|
/* VECTOR LOAD ELEMENT IMMEDIATE */
|
|
.macro VLEIx vr1, imm2, m3, opc
|
|
VX_NUM v1, \vr1
|
|
.word 0xE700 | (VX_R(v1) << 4)
|
|
.word \imm2
|
|
MRXBOPC \m3, \opc, v1
|
|
.endm
|
|
.macro VLEIB vr1, imm2, index
|
|
VLEIx \vr1, \imm2, \index, 0x40
|
|
.endm
|
|
.macro VLEIH vr1, imm2, index
|
|
VLEIx \vr1, \imm2, \index, 0x41
|
|
.endm
|
|
.macro VLEIF vr1, imm2, index
|
|
VLEIx \vr1, \imm2, \index, 0x43
|
|
.endm
|
|
.macro VLEIG vr1, imm2, index
|
|
VLEIx \vr1, \imm2, \index, 0x42
|
|
.endm
|
|
|
|
/* VECTOR LOAD GR FROM VR ELEMENT */
|
|
.macro VLGV gr, vr, disp, base="%r0", m
|
|
GR_NUM r1, \gr
|
|
GR_NUM b2, \base
|
|
VX_NUM v3, \vr
|
|
.word 0xE700 | (r1 << 4) | VX_R(v3)
|
|
.word (b2 << 12) | (\disp)
|
|
MRXBOPC \m, 0x21, v3
|
|
.endm
|
|
.macro VLGVB gr, vr, disp, base="%r0"
|
|
VLGV \gr, \vr, \disp, \base, 0
|
|
.endm
|
|
.macro VLGVH gr, vr, disp, base="%r0"
|
|
VLGV \gr, \vr, \disp, \base, 1
|
|
.endm
|
|
.macro VLGVF gr, vr, disp, base="%r0"
|
|
VLGV \gr, \vr, \disp, \base, 2
|
|
.endm
|
|
.macro VLGVG gr, vr, disp, base="%r0"
|
|
VLGV \gr, \vr, \disp, \base, 3
|
|
.endm
|
|
|
|
/* VECTOR LOAD MULTIPLE */
|
|
.macro VLM vfrom, vto, disp, base
|
|
VX_NUM v1, \vfrom
|
|
VX_NUM v3, \vto
|
|
GR_NUM b2, \base /* Base register */
|
|
.word 0xE700 | (VX_R(v1) << 4) | VX_R(v3)
|
|
.word (b2 << 12) | (\disp)
|
|
MRXBOPC 0, 0x36, v1, v3
|
|
.endm
|
|
|
|
/* VECTOR STORE MULTIPLE */
|
|
.macro VSTM vfrom, vto, disp, base
|
|
VX_NUM v1, \vfrom
|
|
VX_NUM v3, \vto
|
|
GR_NUM b2, \base /* Base register */
|
|
.word 0xE700 | (VX_R(v1) << 4) | VX_R(v3)
|
|
.word (b2 << 12) | (\disp)
|
|
MRXBOPC 0, 0x3E, v1, v3
|
|
.endm
|
|
|
|
/* VECTOR PERMUTE */
|
|
.macro VPERM vr1, vr2, vr3, vr4
|
|
VX_NUM v1, \vr1
|
|
VX_NUM v2, \vr2
|
|
VX_NUM v3, \vr3
|
|
VX_NUM v4, \vr4
|
|
.word 0xE700 | (VX_R(v1) << 4) | VX_R(v2)
|
|
.word (VX_R(v3) << 12)
|
|
MRXBOPC VX_R(v4), 0x8C, v1, v2, v3, v4
|
|
.endm
|
|
|
|
/* VECTOR UNPACK LOGICAL LOW */
|
|
.macro VUPLL vr1, vr2, m3
|
|
VX_NUM v1, \vr1
|
|
VX_NUM v2, \vr2
|
|
.word 0xE700 | (VX_R(v1) << 4) | VX_R(v2)
|
|
.word 0x0000
|
|
MRXBOPC \m3, 0xD4, v1, v2
|
|
.endm
|
|
.macro VUPLLB vr1, vr2
|
|
VUPLL \vr1, \vr2, 0
|
|
.endm
|
|
.macro VUPLLH vr1, vr2
|
|
VUPLL \vr1, \vr2, 1
|
|
.endm
|
|
.macro VUPLLF vr1, vr2
|
|
VUPLL \vr1, \vr2, 2
|
|
.endm
|
|
|
|
|
|
/* Vector integer instructions */
|
|
|
|
/* VECTOR EXCLUSIVE OR */
|
|
.macro VX vr1, vr2, vr3
|
|
VX_NUM v1, \vr1
|
|
VX_NUM v2, \vr2
|
|
VX_NUM v3, \vr3
|
|
.word 0xE700 | (VX_R(v1) << 4) | VX_R(v2)
|
|
.word (VX_R(v3) << 12)
|
|
MRXBOPC 0, 0x6D, v1, v2, v3
|
|
.endm
|
|
|
|
/* VECTOR GALOIS FIELD MULTIPLY SUM */
|
|
.macro VGFM vr1, vr2, vr3, m4
|
|
VX_NUM v1, \vr1
|
|
VX_NUM v2, \vr2
|
|
VX_NUM v3, \vr3
|
|
.word 0xE700 | (VX_R(v1) << 4) | VX_R(v2)
|
|
.word (VX_R(v3) << 12)
|
|
MRXBOPC \m4, 0xB4, v1, v2, v3
|
|
.endm
|
|
.macro VGFMB vr1, vr2, vr3
|
|
VGFM \vr1, \vr2, \vr3, 0
|
|
.endm
|
|
.macro VGFMH vr1, vr2, vr3
|
|
VGFM \vr1, \vr2, \vr3, 1
|
|
.endm
|
|
.macro VGFMF vr1, vr2, vr3
|
|
VGFM \vr1, \vr2, \vr3, 2
|
|
.endm
|
|
.macro VGFMG vr1, vr2, vr3
|
|
VGFM \vr1, \vr2, \vr3, 3
|
|
.endm
|
|
|
|
/* VECTOR GALOIS FIELD MULTIPLY SUM AND ACCUMULATE */
|
|
.macro VGFMA vr1, vr2, vr3, vr4, m5
|
|
VX_NUM v1, \vr1
|
|
VX_NUM v2, \vr2
|
|
VX_NUM v3, \vr3
|
|
VX_NUM v4, \vr4
|
|
.word 0xE700 | (VX_R(v1) << 4) | VX_R(v2)
|
|
.word (VX_R(v3) << 12) | (\m5 << 8)
|
|
MRXBOPC VX_R(v4), 0xBC, v1, v2, v3, v4
|
|
.endm
|
|
.macro VGFMAB vr1, vr2, vr3, vr4
|
|
VGFMA \vr1, \vr2, \vr3, \vr4, 0
|
|
.endm
|
|
.macro VGFMAH vr1, vr2, vr3, vr4
|
|
VGFMA \vr1, \vr2, \vr3, \vr4, 1
|
|
.endm
|
|
.macro VGFMAF vr1, vr2, vr3, vr4
|
|
VGFMA \vr1, \vr2, \vr3, \vr4, 2
|
|
.endm
|
|
.macro VGFMAG vr1, vr2, vr3, vr4
|
|
VGFMA \vr1, \vr2, \vr3, \vr4, 3
|
|
.endm
|
|
|
|
/* VECTOR SHIFT RIGHT LOGICAL BY BYTE */
|
|
.macro VSRLB vr1, vr2, vr3
|
|
VX_NUM v1, \vr1
|
|
VX_NUM v2, \vr2
|
|
VX_NUM v3, \vr3
|
|
.word 0xE700 | (VX_R(v1) << 4) | VX_R(v2)
|
|
.word (VX_R(v3) << 12)
|
|
MRXBOPC 0, 0x7D, v1, v2, v3
|
|
.endm
|
|
|
|
|
|
#endif /* __ASSEMBLY__ */
|
|
#endif /* __ASM_S390_VX_INSN_H */
|