(no commit message)
[libreriscv.git] / openpower / sv / av_opcodes.mdwn
index c03ac65cc21e34c574e1d3d53a64e812a9153bbe..9614d0090532bd0329826cb1b05c0b4224708bfb 100644 (file)
+[[!tag standards]]
+
 # Scalar OpenPOWER Audio and Video Opcodes
 
 the fundamental principle of SV is a hardware for-loop. therefore the first (and in nearly 100% of cases only) place to put Vector operations is first and foremost in the *scalar* ISA.  However only by analysing those scalar opcodes *in* a SV Vectorisation context does it become clear why they are needed and how they may be designed.
 
-This page therefore has acompanying discussion at <https://bugs.libre-soc.org/show_bug.cgi?id=230> for evolution of suitable opcodes.
-
-# Audio
-
-The fundamental principle for these instructions is:
-
-* 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,
-  in order to perform the necessary HI/LO selection normally hard-coded
-  into SIMD ISAs.
-
-Thus for example, where OpenPOWER VSX has vpkswss, this would be achieved in SV with simply:
-
-* addition of a scalar ext/clamp instruction
-* 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)
-
-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.
-
-## Scalar element operations
-
-* 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
-
-# Video
-
-TODO
-
-* DCT <https://users.cs.cf.ac.uk/Dave.Marshall/Multimedia/node231.html>
-* <https://www.nayuki.io/page/fast-discrete-cosine-transform-algorithms>
-
-# VSX SIMD
-
-Useful parts of VSX, and how they might map.
-
-## vpks[\*][\*]s (vec_pack*)
+This page therefore has accompanying discussion at <https://bugs.libre-soc.org/show_bug.cgi?id=230> for evolution of suitable opcodes.
 
-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.
+Links
 
-The other direction, vec_unpack widening ops, may need some way to tell whether to sign-extend or zero-extend.
-## vavgs\* (vec_avg)
+* <https://bugs.libre-soc.org/show_bug.cgi?id=915> add overflow to maxmin.
+* <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>
 
-signed and unsigned, 8/16/32: these are all of the form:
+# Summary
 
-    result = truncate((a + b + 1) >> 1))
+In-advance, the summary of base scalar operations that need to be added is:
 
-## vabsdu\* (vec_abs)
+| instruction   | pseudocode               |
+| ------------  | ------------------------      |
+| 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 [[ls013]] |
+| (un)signed max| result = (src1 > src2) ? src1 : src2 [[ls013]]  |
+| bitwise sel   | (a ? b : c) - use [[sv/bitmanip]] ternary |
+| int/fp move   | covered by REMAP and Pack/Unpack |
 
-unsigned 8/16/32: these are all of the form:
+Implemented at the [[openpower/isa/av]] pseudocode page.
 
-    result = (src1 > src2) ? truncate(src1-src2) :
-                             truncate(src2-src1)
+All other capabilities (saturate in particular) are achieved with [[sv/svp64]] modes and swizzle.  Note that minmax and ternary are added in bitmanip.
 
-## vmaxs\* / vmaxu\* (and min)
+# Instructions
 
-signed and unsigned, 8/16/32: these are all of the form:
+## Average Add
 
-    result = (src1 > src2) ? src1 : src2 # max
-    result = (src1 < src2) ? src1 : src2 # min
+X-Form
 
-## vmerge operations
+* avgadd  RT,RA,RB (Rc=0)
+* avgadd. RT,RA,RB (Rc=1)
 
-Their main point was to work around the odd/even multiplies. SV swizzles and mv.x should handle all cases.
+Pseudo-code:
 
-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.
+    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]
 
-in the swizzle case the first instruction would be destvect2.X = srcvec2.X and the second would swizzle-select Y.  macro-op fusion in both the prefixated variant and the swizzle variant would interleave the two into the same SIMD backend ALUs.
+Special Registers Altered:
 
-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 vectir prefixing)
+    CR0                     (if Rc=1)
 
-## Float estimates
+## Absolute Signed Difference
 
-    vec_expte - float 2^x
-    vec_loge - float log2(x)
-    vec_re - float 1/x
-    vec_rsqrte - float 1/sqrt(x)
+X-Form
 
-The spec says the max relative inaccuracy is 1/4096.
+* absds  RT,RA,RB (Rc=0)
+* absds. RT,RA,RB (Rc=1)
 
-*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"
+Pseudo-code:
 
-## vec_madd(s) - FMA, multiply-add, optionally saturated
+    if (RA) < (RB) then RT <- ¬(RA) + (RB) + 1
+    else                RT <- ¬(RB) + (RA) + 1
 
-    a * b + c
+Special Registers Altered:
 
-*Standard scalar madd*
+    CR0                     (if Rc=1)
 
-## vec_msum(s) - horizontal gather multiply-add, optionally saturated
+## Absolute Unsigned Difference
 
-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.
+X-Form
 
-    a.x + a.y + a.z ...
-    a.x * a.y * a.z ...
+* absdu  RT,RA,RB (Rc=0)
+* absdu. RT,RA,RB (Rc=1)
 
-*This would realistically need to be done with a loop doing a mapreduce.  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.  An OoO multi-issue engine woukd be more than capable of desling with the Dependencies.*
+Pseudo-code:
 
-## vec_mul*
+    if (RA) <u (RB) then RT <- ¬(RA) + (RB) + 1
+    else                RT <- ¬(RB) + (RA) + 1
 
-There should be both a same-width multiply and a widening multiply. Signed and unsigned versions. Optionally saturated.
+Special Registers Altered:
 
-    u8 * u8 = u8
-    u8 * u8 = u16
+    CR0                     (if Rc=1)
 
-For 8,16,32,64, resulting in 8,16,32,64,128.
+## Absolute Accumulate Unsigned Difference
 
-*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.  Specifying src elwidth=8 and dest elwidth=16 will give a widening multiply*
+X-Form
 
-## vec_rl - rotate left
+* absdacu  RT,RA,RB (Rc=0)
+* absdacu. RT,RA,RB (Rc=1)
 
-    (a << x) | (a >> (WIDTH - x))
+Pseudo-code:
 
-*Standard scalar rlwinm*
+    if (RA) <u (RB) then r <- ¬(RA) + (RB) + 1
+    else                 r <- ¬(RB) + (RA) + 1
+    RT <- (RT) + r
 
-## vec_sel - bitwise select
+Special Registers Altered:
 
-    (a ? b : c)
+    CR0                     (if Rc=1)
 
-## vec_splat - scatter
+## Absolute Accumulate Signed Difference
 
-Implemented using swizzle/predicate.
+X-Form
 
-## vec_perm - permute
+* absdacs  RT,RA,RB (Rc=0)
+* absdacs. RT,RA,RB (Rc=1)
 
-Implemented using swizzle, mv.x.
+Pseudo-code:
 
-## vec_*c[tl]z, vec_popcnt - count leading/trailing zeroes, set bits
+    if (RA) < (RB) then r <- ¬(RA) + (RB) + 1
+    else                r <- ¬(RB) + (RA) + 1
+    RT <- (RT) + r
 
-Bit counts.
+Special Registers Altered:
 
-    ctz - count trailing zeroes
-    clz - count leading zeroes
-    popcnt - count set bits
+    CR0                     (if Rc=1)