(no commit message)
[libreriscv.git] / openpower / sv / av_opcodes.mdwn
index dadcf72d19b05b2ee2e0b5e760541dc2f574b838..9614d0090532bd0329826cb1b05c0b4224708bfb 100644 (file)
@@ -12,9 +12,11 @@ Links
 * <https://bugs.libre-soc.org/show_bug.cgi?id=863> add pseudocode etc.
 * <https://bugs.libre-soc.org/show_bug.cgi?id=234> hardware implementation
 * <https://bugs.libre-soc.org/show_bug.cgi?id=910> mins/maxs zero-option?
+* <https://bugs.libre-soc.org/show_bug.cgi?id=1057> move all int/fp min/max to ls013
 * [[vpu]]
 * [[sv/int_fp_mv]]
 * [[openpower/isa/av]] pseudocode
+* [[av_opcodes/analysis]]
 * TODO review HP 1994-6 PA-RISC MAX <https://en.m.wikipedia.org/wiki/Multimedia_Acceleration_eXtensions>
 * <https://en.m.wikipedia.org/wiki/Sum_of_absolute_differences>
 * List of MMX instructions <https://cs.fit.edu/~mmahoney/cse3101/mmx.html>
@@ -28,229 +30,99 @@ In-advance, the summary of base scalar operations that need to be added is:
 | average-add.  | result = (src1 + src2 + 1) >> 1 |
 | abs-diff      | result = abs (src1-src2) |
 | abs-accumulate| result += abs (src1-src2) |
-| (un)signed min| result = (src1 < src2) ? src1 : src2 use bitmanip |
-| (un)signed max| result = (src1 > src2) ? src1 : src2  use bitmanip |
+| (un)signed min| result = (src1 < src2) ? src1 : src2 [[ls013]] |
+| (un)signed max| result = (src1 > src2) ? src1 : src2 [[ls013]]  |
 | bitwise sel   | (a ? b : c) - use [[sv/bitmanip]] ternary |
-| int/fp move   | covered by [[sv/int_fp_mv]] |
+| int/fp move   | covered by REMAP and Pack/Unpack |
 
 Implemented at the [[openpower/isa/av]] pseudocode page.
 
 All other capabilities (saturate in particular) are achieved with [[sv/svp64]] modes and swizzle.  Note that minmax and ternary are added in bitmanip.
 
-# Audio
+# Instructions
 
-The fundamental principle for these instructions is:
+## Average Add
 
-* identify the scalar primitive
-* assume that longer runs of scalars will have Simple-V vectorisatin applied
-* assume that "swizzle" may be applied at the (vec2 - SUBVL=2) Vector level,
- (even if that involves a mv.swizxle which may be macro-op fused)
-  in order to perform the necessary HI/LO selection normally hard-coded
-  into SIMD ISAs.
+X-Form
 
-Thus for example, where OpenPOWER VSX has vpkswss, this would be achieved in SV with simply:
+* avgadd  RT,RA,RB (Rc=0)
+* avgadd. RT,RA,RB (Rc=1)
 
-* applying saturation to minu (sv.minu/satu)
-* 1st op, swizzle-selection vec2 "select X only" from source to dest:
-  dest.X = extclamp(src.X)
-* 2nd op, swizzle-select vec2 "select Y only" from source to dest
-  dest.Y = extclamp(src.Y)
+Pseudo-code:
 
-Macro-op fusion may be used to detect that these two interleave cleanly, overlapping the vec2.X with vec2.Y to produce a single vec2.XY operation.
+    a <- [0] * (XLEN+1)
+    b <- [0] * (XLEN+1)
+    a[1:XLEN] <- (RA)
+    b[1:XLEN] <- (RB)
+    r <- (a + b + 1)
+    RT <- r[0:XLEN-1]
 
-Alternatively Twin-Predication may be applied, with every even bit set in
-the source mask and every odd bit set in the destination mask:
+Special Registers Altered:
 
-    r3=0b10101010
-    r10=0b01010101
-    r0=0x00007fff # or other limit
-    sv.minu/satu/sm=r3/dm=r10/ew=32 *r20,*r20,r0
+    CR0                     (if Rc=1)
 
-## Scalar element operations
+## Absolute Signed Difference
 
-* clamping / saturation for signed and unsigned.  best done similar to FP rounding modes, i.e. with an SPR.
-* average-add.  result = (src1 + src2 + 1) >> 1
-* abs-diff: result = (src1 > src2) ? (src1-src2) : (src2-src1)
-* signed min/max
+X-Form
 
-# Video
+* absds  RT,RA,RB (Rc=0)
+* absds. RT,RA,RB (Rc=1)
 
-* DCT added as [[sv/remap]] <https://users.cs.cf.ac.uk/Dave.Marshall/Multimedia/node231.html>
- <https://www.nayuki.io/page/fast-discrete-cosine-transform-algorithms>
-* Absolute-diff Accumulation, used in Motion Estimation, added,
-  see [[sv/bitmanip]] and opcodes in [[openpower/isa/av]]
+Pseudo-code:
 
-# VSX SIMD analysis
+    if (RA) < (RB) then RT <- ¬(RA) + (RB) + 1
+    else                RT <- ¬(RB) + (RA) + 1
 
-Useful parts of VSX, and how they might map.
+Special Registers Altered:
 
-## vpks[\*][\*]s (vec_pack*)
+    CR0                     (if Rc=1)
 
-signed and unsigned, these are N-to-M (N=64/32/16, M=32/16/8) chop/clamp/sign/zero-extend operations. May be implemented by a clamped move to a smaller elwidth.
+## Absolute Unsigned Difference
 
-The other direction, vec_unpack widening ops, may need some way to tell whether to sign-extend or zero-extend.
+X-Form
 
-*scalar extsw/b/h gives one set, mv gives another.  src elwidth override and dest elwidth override provide the pack/unpack*.
+* absdu  RT,RA,RB (Rc=0)
+* absdu. RT,RA,RB (Rc=1)
 
-implemented by Pack/Unpack. [[sv/normal]] arithmetic also has Pack-with-Saturate.
-## vavgs\* (vec_avg)
+Pseudo-code:
 
-signed and unsigned, 8/16/32: these are all of the form:
+    if (RA) <u (RB) then RT <- ¬(RA) + (RB) + 1
+    else                RT <- ¬(RB) + (RA) + 1
 
-    result = truncate((a + b + 1) >> 1))
+Special Registers Altered:
 
-*These do not exist in scalar ISA and would need to be added.  Essentially it is a type of post-processing involving the CA bit so could be included in the existing scalar pipeline ALU*
+    CR0                     (if Rc=1)
 
-## vabsdu\* (vec_abs)
+## Absolute Accumulate Unsigned Difference
 
-unsigned 8/16/32: these are all of the form:
+X-Form
 
-    result = (src1 > src2) ? truncate(src1-src2) :
-                             truncate(src2-src1)
+* absdacu  RT,RA,RB (Rc=0)
+* absdacu. RT,RA,RB (Rc=1)
 
-*These do not exist in the scalar ISA and would need to be added*
+Pseudo-code:
 
-## abs-accumulate
+    if (RA) <u (RB) then r <- ¬(RA) + (RB) + 1
+    else                 r <- ¬(RB) + (RA) + 1
+    RT <- (RT) + r
 
-signed and unsigned variants needed:
+Special Registers Altered:
 
-    result += (src1 > src2) ? truncate(src1-src2) :
-                              truncate(src2-src1)
+    CR0                     (if Rc=1)
 
-*These do not exist in the scalar ISA and would need to be added*
+## Absolute Accumulate Signed Difference
 
-## vmaxs\* / vmaxu\* (and min)
+X-Form
 
-signed and unsigned, 8/16/32: these are all of the form:
+* absdacs  RT,RA,RB (Rc=0)
+* absdacs. RT,RA,RB (Rc=1)
 
-    result = (src1 > src2) ? src1 : src2 # max
-    result = (src1 < src2) ? src1 : src2 # min
+Pseudo-code:
 
-*These do not exist in the scalar INTEGER ISA and would need to be added*.
-There are additionally no scalar FP min/max, either. These also
-need to be added.
+    if (RA) < (RB) then r <- ¬(RA) + (RB) + 1
+    else                r <- ¬(RB) + (RA) + 1
+    RT <- (RT) + r
 
-Also it makes sense for both the integer and FP variants
-to have Rc=1 modes, where those modes are based on the
-respective cmp (or fsel / isel) behaviour. In other words,
-the Rc=1 setting is based on the *comparison* of the
-two inputs, rather than on which of the two results was
-returned by the min/max opcode.
+Special Registers Altered:
 
-    result = (src1 > src2) ? src1 : src2 # max
-    CR0 = CR_computr(src2-src1) # not based on result
-
-## vmerge operations
-
-Their main point was to work around the odd/even multiplies. SV swizzles and mv.x should handle all cases.
-
-these take two src vectors of various widths and splice them together.  the best technique to cover these is a simple straightforward predicated pair of mv operations, inverting the predicate in the second case, or, alternately, to use a pair of vec2 (SUBVL=2) swizzled operations.
-
-in the swizzle case the first instruction would be destvec2.X = srcvec2.X and the second would swizzle-select Y: destvec2.Y = srcvec2.Y.  macro-op fusion in both the predicated variant and the swizzle variant would interleave the two into the same SIMD backend ALUs (or macro-op fusion identifies the patterns)
-
-with twin predication the elwidth can be overridden on both src and dest such that either straight scalar mv or extsw/b/h can be used to provide the combinations of coverage needed, with only 2 actual instructions (plus vector prefixing)
-
-See [[sv/mv.vec]] and [[sv/mv.swizzle]]
-
-## Float estimates
-
-    vec_expte - float 2^x
-    vec_loge - float log2(x)
-    vec_re - float 1/x
-    vec_rsqrte - float 1/sqrt(x)
-
-The spec says the max relative inaccuracy is 1/4096.
-
-*In conjunction with the FPSPR "accuracy" bit These could be done by assigning meaning to the "sat mode" SVP64 bits in a FP context. 0b00 is IEEE754 FP, 0b01 is 2^12 accuracy for FP32. These can be applied to standard scalar FP ops*
-
-The other alternative is to use the "single precision" FP operations on a 32-bit elwidth override.  As explained in [[sv/fcvt]] this halves the precision,
-operating at FP16 accuracy but storing in a FP32 format.
-
-## vec_madd(s) - FMA, multiply-add, optionally saturated
-
-    a * b + c
-
-*Standard scalar madd*
-
-## vec_msum(s) - horizontal gather multiply-add, optionally saturated
-
-This should be separated to a horizontal multiply and a horizontal add. How a horizontal operation would work in SV is TBD, how wide is it, etc.
-
-    a.x + a.y + a.z ...
-    a.x * a.y * a.z ...
-
-*This would realistically need to be done with a loop doing a mapreduce sequence.  I looked very early on at doing this type of operation and concluded it would be better done with a series of halvings each time, as separate instructions:  VL=16 then VL=8 then 4 then 2 and finally one scalar.  i.e. not an actual part of SV al all. An OoO multi-issue engine would be more than capable of dealing with the Dependencies.*
-
-That has the issue that's it's a massive PITA to code, plus it's slow. Plus there's the "access to non-4-offset regs stalls". Even if there's no ready operation, it should be made easier and faster than a manual mapreduce loop.
-
---
-
-As a mid-solution, 4-element gathers were discussed. 4 elements would also make them useful for pixel packing, not just the general vector gather. This is because OR and ADD are the same operation when bits don't overlap.
-
-    gather-add: d = a.x + a.y + a.z + a.w
-    gather-mul: d = a.x * a.y * a.z * a.w
-
-But can the SV loop increment the src reg # by 4? Hmm.
-
-The idea then leads to the opposite operation, a 1-to-4 bit scatter instruction. Like gather, it could be implemented with a normal loop, but it's faster for certain uses.
-
-    bit-scatter dest, src, bits
-
-    bit-scatter rd, rs, 8 # assuming source and dest are 32-bit wide
-    rd = (rs >> 0 * 8) & (2^8 - 1)
-    rd+1 = (rs >> 1 * 8) & (2^8 - 1)
-    rd+2 = (rs >> 2 * 8) & (2^8 - 1)
-    rd+3 = (rs >> 3 * 8) & (2^8 - 1)
-
-So at the start you have a RGBA packed pixel in one 32-bit register, at the end you have each channel separated into its own register, in the low bits, and ANDed so only the relevant bits are there.
-
-## vec_mul*
-
-There should be both a same-width multiply and a widening multiply. Signed and unsigned versions. Optionally saturated.
-
-    u8 * u8 = u8
-    u8 * u8 = u16
-
-For 8,16,32,64, resulting in 8,16,32,64,128.
-
-*All of these can be done with SV elwidth overrides, as long as the dest is no greater than 128.  SV specifically does not do 128 bit arithmetic. Instead, vec2.X mul-lo followed by vec2.Y mul-hi can be macro-op fused to get at the full 128 bit internal result.  Specifying e.g. src elwidth=8 and dest elwidth=16 will give a widening multiply*
-
-(Now added `maddedu` which is twin-half 64x64->HI64/LO64 in [[sv/biginteger]])
-
-## vec_rl - rotate left
-
-    (a << x) | (a >> (WIDTH - x))
-
-*Standard scalar rlwinm*
-
-## vec_sel - bitwise select
-
-    (a ? b : c)
-
-*This does not exist in the scalar ISA and would need to be added*
-
-Interesting operation: Tim.Forsyth's video on Larrabee they added a logical ternary lookup table op, which can cover this and more.  similar to crops 2-2 bit lookup.
-
-* <http://0x80.pl/articles/avx512-ternary-functions.html>
-* <https://github.com/WojciechMula/ternary-logic/blob/master/py/show-function.py>
-* [[sv/bitmanip]]
-
-
-## vec_splat - scatter
-
-Implemented using swizzle/predicate.
-
-## vec_perm - permute
-
-Implemented using swizzle, mv.x.
-
-## vec_*c[tl]z, vec_popcnt - count leading/trailing zeroes, set bits
-
-Bit counts.
-
-    ctz - count trailing zeroes
-    clz - count leading zeroes
-    popcnt - count set bits
-
-*These all exist in the scalar ISA*
+    CR0                     (if Rc=1)