(no commit message)
[libreriscv.git] / openpower / sv / mv.vec.mdwn
1 [[!tag standards]]
2
3 # Vector mv operations
4
5 In the SIMD VSX set, section 6.8.1 and 6.8.2 p254 of v3.0B has a series of pack and unpack operations. This page covers those and more. [[svp64]] provides the Vector Context to also add saturation as well as predication.
6
7 See <https://bugs.libre-soc.org/show_bug.cgi?id=230#c30>
8
9 Note that some of these may be covered by [[remap]].
10
11 # move to/from vec2/3/4
12
13 Basic idea: mv operations where either the src or dest is specifically marked as having SUBVL apply to it, but, crucially, the *other* argument does *not*. Note that this is highly unusual in SimpleV, which normally only allows SUBVL to be applied uniformly across all dest and all src.
14
15 mv.srcvec r3, r4.vec2
16 mv.destvec r2.vec4, r5
17
18 TODO: evaluate whether this will fit with [[mv.swizzle]] involved as well
19 (yes it probably will)
20
21 * M=0 is mv.srcvec
22 * M=1 is mv.destvec
23
24 mv.srcvec (leaving out elwidths and chop):
25
26 for i in range(VL):
27 regs[rd+i] = regs[rs+i*SUBVL]
28
29 mv.destvec (leaving out elwidths and chop):
30
31 for i in range(VL):
32 regs[rd+i*SUBVL] = regs[rs+i]
33
34 Note that these mv operations only become significant when elwidth is set on the vector to a small value. SUBVL=4, src elwidth=8, dest elwidth=32 for example.
35
36 intended to cover:
37
38 rd = (rs >> 0 * 8) & (2^8 - 1)
39 rd+1 = (rs >> 1 * 8) & (2^8 - 1)
40 rd+2 = (rs >> 2 * 8) & (2^8 - 1)
41 rd+3 = (rs >> 3 * 8) & (2^8 - 1)
42
43 and variants involving vec3 into 32 bit (4th byte set to zero).
44 TODO: include this pseudocode which shows how the vecN can do that.
45 in this example RA elwidth=32 and RB elwidth=8, RB is a vec4.
46
47 for i in range(VL):
48 if predicate_bit_not_set(i) continue
49 uint8_t *start_point = (uint8_t*)(int_regfile[RA].i[i])
50 for j in range(SUBVL): # vec4
51 start_point[j] = some_op(int_regfile[RB].b[i*SUBVL + j])
52
53 ## Twin Predication, saturation, swizzle, and elwidth overrides
54
55 Note that mv is a twin-predicated operation, and is swizzlable. This implies that from the vec2, vec3 or vec4, 1 to 8 bytes may be selected and re-ordered (XYZW), mixed with 0 and 1 constants, skipped by way of twin predicate pack and unpack, and a huge amount besides.
56
57 Also saturation can be applied to individual elements, including the elements within a vec2/3/4.
58
59 # mv.zip and unzip
60
61 These are Scalar equivalents to VSX Pack and Unpack: v3.1
62 Book I Section 6.8 p278. Saturated variants do not need
63 adding because SVP64 overrides add Saturation already.
64 More detailed merging may be achieved with [[sv/bitmanip]]
65 instructions.
66
67 | 0.5 |6.10|11.15|16..20|21..25|26.....30|31| name |
68 |-----|----|-----|------|------|---------|--|--------------|
69 | 19 | RTp| RC | RB/0 | RA/0 | XO[5:9] |Rc| mv.zip |
70 | 19 | RT | RC | RS/0 | RA/0 | XO[5:9] |Rc| mv.unzip |
71
72 these are specialist operations that zip or unzip to/from multiple regs to/from one vector including vec2/3/4. when SUBVL!=1 the vec2/3/4 is the contiguous unit that is copied (as if one register). different elwidths result in zero-extension or truncation except if saturation is enabled, where signed/unsigned may be applied as usual.
73
74 mv.zip, RA=0, RB=0
75
76 for i in range(VL):
77 regs[rt+i] = regs[rc+i]
78
79 mv.zip, RA=0, RB!=0
80
81 for i in range(VL):
82 regs[rt+i*2 ] = regs[rb+i]
83 regs[rt+i*2+1] = regs[rc+i]
84
85 mv.zip, RA!=0, RB!=0
86
87 for i in range(VL):
88 regs[rt+i*3 ] = regs[rb+i]
89 regs[rt+i*3+1] = regs[rc+i]
90 regs[rt+i*3+2] = regs[ra+i]
91
92 # REMAP concept for pack/unpack
93
94 It may be possible to use one standard mv instruction to perform packing
95 and unpacking: Matrix allows for both reordering and offsets. At the very least a predicate mask potentially can
96 be used.
97
98 * If a single src-dest mv is used, then it potentially requires
99 two separate REMAP and two separate sv.mvs: remap-even, sv.mv,
100 remap-odd, sv.mv
101 * If adding twin-src and twin-dest that is a lot of instructions,
102 particularly if triple is added as well. FPR mv, GPR mv
103 * Unless twin or triple is added, how is it possible to determine
104 the extra register(s) to be merged (or split)?
105
106 How about instead relying on the implicit RS=MAXVL+RT trick and
107 extending that to RS=MAXVL+RA as a source? One spare bit in the
108 EXTRA RM area says whether the sv.mv is a pack (RS-as-src=RA+MAXVL)
109 or unpack (RS-as-dest=RT+MAXVL)
110
111 Alternatively, given that Matrix is up to 3 Dimensions, not even
112 be concerned about RS, just simply use one of those dimensions to
113 span the packing:
114
115 Example 1:
116
117 * RA set to linear
118 * RT set to YX, ydim=2, xdim=4
119 * VL=MAXVL=8
120
121 | RA | (0 1) (2 3) (4 5) (6 7) |
122 | RT | 0 2 4 8 1 3 5 7 |
123
124 This results in a 2-element "unpack"
125
126 Example 2:
127
128 * RT set to linear
129 * RT set to YX, ydim=3, xdim=3
130 * VL=MAXVL=9
131
132 | RA | 0 1 2 3 4 5 6 7 8 |
133 | RT | (0 3 6) (1 4 7) (2 5 8) |
134
135 This results in a 3-element "pack"
136
137 Both examples become particularly fun when Twin Predication is thrown
138 into the mix.
139
140