[PR] swscale: refactor sw_ops to test uops directly (PR #23734)

Niklas Haas via ffmpeg-devel <[email protected]> Wed, 08 Jul 2026 00:18:31 -0000
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <178346991205.59.11033298152386869044@29965ddac10e>
PR #23734 opened by Niklas Haas (haasn)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23734
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23734.patch

Rather than awkwardly un-translating them back to the equivalent SwsOp and hoping that it gets compiled back to the same uop.

The immediate downside is that we no longer test the memcpy backend, nor the pshufb fast path; but the latter will be fixed by #23440. Not testing the memcpy backend is a bit of a moot point though as the memcpy backend is already covered by the fate-sws-unscaled test.


>From 920a4a86fa5ed1c939beb277132d4e6899f98887 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Fri, 12 Jun 2026 11:33:59 +0200
Subject: [PATCH 01/10] swscale/ops_dispatch: remove outdated comment

Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/ops_dispatch.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/libswscale/ops_dispatch.h b/libswscale/ops_dispatch.h
index 2cc4aa3490..584e2a123e 100644
--- a/libswscale/ops_dispatch.h
+++ b/libswscale/ops_dispatch.h
@@ -135,8 +135,7 @@ typedef struct SwsOpBackend {
     SwsBackend flags; /* Set of SWS_BACKEND_* */
 
     /**
-     * Compile an operation list to an implementation chain. May modify `ops`
-     * freely; the original list will be freed automatically by the caller.
+     * Compile an operation list to an implementation chain.
      *
      * Returns 0 or a negative error code.
      */
-- 
2.52.0


>From cf163c19aece9c59931a0c7672bdabbe0732d72e Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Fri, 12 Jun 2026 12:12:52 +0200
Subject: [PATCH 02/10] swscale/uops: add extra convenience metadata for the
 backends

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/uops.c | 14 +++++++++++++-
 libswscale/uops.h |  5 +++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/libswscale/uops.c b/libswscale/uops.c
index f8af9c41c2..2c9916d4ed 100644
--- a/libswscale/uops.c
+++ b/libswscale/uops.c
@@ -330,6 +330,13 @@ static int translate_rw_op(SwsContext *ctx, SwsUOpList *ops, SwsUOpFlags flags,
         uop.uop = is_read ? SWS_UOP_READ_PLANAR : SWS_UOP_WRITE_PLANAR;
     }
 
+    const int planes = ff_sws_rw_op_planes(op);
+    if (op->op == SWS_OP_READ) {
+        ops->planes_in  |= SWS_COMP_ELEMS(planes);
+    } else {
+        ops->planes_out |= SWS_COMP_ELEMS(planes);
+    }
+
     return ff_sws_uop_list_append(ops, &uop);
 }
 
@@ -687,7 +694,12 @@ int ff_sws_ops_translate(SwsContext *ctx, const SwsOpList *ops,
 {
     SwsComps input = ops->comps_src;
     for (int i = 0; i < ops->num_ops; i++) {
-        int ret = translate_op(ctx, uops, flags, &ops->ops[i], &input);
+        const SwsOp *op = &ops->ops[i];
+        const int pixel_size = ff_sws_pixel_type_size(op->type);
+        if (pixel_size > uops->pixel_size_max)
+            uops->pixel_size_max = pixel_size;
+
+        int ret = translate_op(ctx, uops, flags, op, &input);
         if (ret < 0)
             return ret;
         input = ops->ops[i].comps;
diff --git a/libswscale/uops.h b/libswscale/uops.h
index 1ad14efc58..bea017268a 100644
--- a/libswscale/uops.h
+++ b/libswscale/uops.h
@@ -255,6 +255,11 @@ void ff_sws_uop_name(const SwsUOp *op, char buf[SWS_UOP_NAME_MAX]);
 typedef struct SwsUOpList {
     SwsUOp *ops;
     int num_ops;
+
+    /* Additional metadata for implementations */
+    SwsCompMask planes_in;  /* mask of planes read from */
+    SwsCompMask planes_out; /* mask of planes written to */
+    int pixel_size_max;     /* size of largest pixel type seen in any uop */
 } SwsUOpList;
 
 SwsUOpList *ff_sws_uop_list_alloc(void);
-- 
2.52.0


>From 09653663a2ab0add4b7a4503a8c90d6f5e88e2c1 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Fri, 12 Jun 2026 12:13:39 +0200
Subject: [PATCH 03/10] swscale/x86/ops: avoid direct reliance on `ops`
 metadata

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/x86/ops.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/libswscale/x86/ops.c b/libswscale/x86/ops.c
index 31c2199622..60550b7ff4 100644
--- a/libswscale/x86/ops.c
+++ b/libswscale/x86/ops.c
@@ -611,7 +611,7 @@ static int compile(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out)
 
     *out = (SwsCompiledOp) {
         /* Use at most two full YMM regs during the widest precision section */
-        .block_size  = 2 * FFMIN(mmsize, 32) / ff_sws_op_list_max_size(ops),
+        .block_size  = 2 * FFMIN(mmsize, 32) / uops->pixel_size_max,
         .slice_align = 1,
         .free        = ff_sws_op_chain_free_cb,
         .priv        = chain,
@@ -634,11 +634,7 @@ static int compile(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out)
             goto fail;
     }
 
-    const SwsOp *read      = ff_sws_op_list_input(ops);
-    const SwsOp *write     = ff_sws_op_list_output(ops);
-    const int read_planes  = read ? ff_sws_rw_op_planes(read) : 0;
-    const int write_planes = ff_sws_rw_op_planes(write);
-    switch (FFMAX(read_planes, write_planes)) {
+    switch (av_popcount(uops->planes_in | uops->planes_out)) {
     case 1: out->func = ff_sws_process1_x86; break;
     case 2: out->func = ff_sws_process2_x86; break;
     case 3: out->func = ff_sws_process3_x86; break;
-- 
2.52.0


>From 87ae780cefeef328b46f1c6cc04b11cd7aba1b99 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Fri, 12 Jun 2026 12:14:25 +0200
Subject: [PATCH 04/10] swscale/ops_dispatch: add SwsOpBackend.compile_uops()

This can be used as an alternative to the existing compile() backend, that
takes SwsUOpList instead of SwsOpList.

Down the line, I plan on also moving the uops translation to the dispatch
layer itself, but this requires some further changes which have not yet
been merged, so this commit represents a stopgap solution.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/ops_dispatch.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/libswscale/ops_dispatch.h b/libswscale/ops_dispatch.h
index 584e2a123e..f88ba63825 100644
--- a/libswscale/ops_dispatch.h
+++ b/libswscale/ops_dispatch.h
@@ -25,6 +25,7 @@
 
 #include "libavutil/frame.h"
 #include "graph.h"
+#include "uops.h"
 
 /**
  * Global execution context for all compiled functions.
@@ -141,6 +142,11 @@ typedef struct SwsOpBackend {
      */
     int (*compile)(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out);
 
+    /**
+     * Alternative to `compile` that takes a list of micro-ops directly.
+     */
+    int (*compile_uops)(SwsContext *ctx, const SwsUOpList *uops, SwsCompiledOp *out);
+
     /**
      * If NONE, backend only supports software frames.
      * Otherwise, frame hardware format must match hw_format for the backend
-- 
2.52.0


>From aaa4eec00467fdeb45460c568899640a2899dda9 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Fri, 12 Jun 2026 12:18:14 +0200
Subject: [PATCH 05/10] swscale/uops_backend: implement compile_uops()

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/uops_backend.c | 40 ++++++++++++++++++++++-----------------
 1 file changed, 23 insertions(+), 17 deletions(-)

diff --git a/libswscale/uops_backend.c b/libswscale/uops_backend.c
index 69d607c958..d0d05ee42f 100644
--- a/libswscale/uops_backend.c
+++ b/libswscale/uops_backend.c
@@ -135,7 +135,7 @@ static void process(const SwsOpExec *exec, const void *priv,
     }
 }
 
-static int compile(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out)
+static int compile_uops_c(SwsContext *ctx, const SwsUOpList *uops, SwsCompiledOp *out)
 {
     int ret;
 
@@ -143,16 +143,6 @@ static int compile(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out)
     if (!chain)
         return AVERROR(ENOMEM);
 
-    SwsUOpList *uops = ff_sws_uop_list_alloc();
-    if (!uops) {
-        ret = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    ret = ff_sws_ops_translate(ctx, ops, 0, uops);
-    if (ret < 0)
-        goto fail;
-
     av_assert0(uops->num_ops > 0);
     for (int i = 0; i < uops->num_ops; i++) {
         const SwsUOpTable *table = &uop_table;
@@ -181,18 +171,34 @@ static int compile(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out)
         av_log(ctx, AV_LOG_DEBUG, "    %s\n", name);
     }
 
-    ff_sws_uop_list_free(&uops);
     return 0;
 
 fail:
-    ff_sws_uop_list_free(&uops);
     ff_sws_op_chain_free(chain);
     return ret;
 }
 
+static int compile_c(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out)
+{
+    SwsUOpList *uops = ff_sws_uop_list_alloc();
+    if (!uops)
+        return AVERROR(ENOMEM);
+
+    int ret = ff_sws_ops_translate(ctx, ops, 0, uops);
+    if (ret < 0)
+        goto fail;
+
+    ret = compile_uops_c(ctx, uops, out);
+
+fail:
+    ff_sws_uop_list_free(&uops);
+    return ret;
+}
+
 const SwsOpBackend backend_c = {
-    .name       = "c",
-    .flags      = SWS_BACKEND_C,
-    .compile    = compile,
-    .hw_format  = AV_PIX_FMT_NONE,
+    .name           = "c",
+    .flags          = SWS_BACKEND_C,
+    .compile        = compile_c,
+    .compile_uops   = compile_uops_c,
+    .hw_format      = AV_PIX_FMT_NONE,
 };
-- 
2.52.0


>From 79a84f383f6e56a5ec82aae89ff3118e43e4e720 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Tue, 7 Jul 2026 14:10:59 +0200
Subject: [PATCH 06/10] swscale/x86/ops: implement compile_uops()

This also splits off the mmsize determination to a separate helper,
to make the code a bit more reusable.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/x86/ops.c | 94 +++++++++++++++++++++++++++-----------------
 1 file changed, 57 insertions(+), 37 deletions(-)

diff --git a/libswscale/x86/ops.c b/libswscale/x86/ops.c
index 60550b7ff4..b3e0222bb0 100644
--- a/libswscale/x86/ops.c
+++ b/libswscale/x86/ops.c
@@ -484,6 +484,19 @@ SWS_DECL_FUNC(ff_sws_process2_x86);
 SWS_DECL_FUNC(ff_sws_process3_x86);
 SWS_DECL_FUNC(ff_sws_process4_x86);
 
+static int get_mmsize(void)
+{
+    const int cpu_flags = av_get_cpu_flags();
+    if (EXTERNAL_AVX512(cpu_flags))
+        return 64;
+    else if (EXTERNAL_AVX2(cpu_flags))
+        return 32;
+    else if (EXTERNAL_SSE4(cpu_flags))
+        return 16;
+    else
+        return AVERROR(ENOTSUP);
+}
+
 static int movsize(const int bytes, const int mmsize)
 {
     return bytes <= 4 ? 4 : /* movd */
@@ -491,12 +504,16 @@ static int movsize(const int bytes, const int mmsize)
            mmsize;          /* movu */
 }
 
-static int solve_shuffle(const SwsOpList *ops, int mmsize, SwsCompiledOp *out)
+static int solve_shuffle(const SwsOpList *ops, SwsCompiledOp *out)
 {
     uint8_t shuffle[16];
+    int mmsize = get_mmsize();
     int read_bytes, write_bytes;
     int pixels;
 
+    if (mmsize < 0)
+        return mmsize;
+
     /* Solve the shuffle mask for one 128-bit lane only */
     pixels = ff_sws_solve_shuffle(ops, shuffle, 16, 0x80, &read_bytes, &write_bytes);
     if (pixels < 0)
@@ -573,42 +590,16 @@ static void normalize_clear(SwsUOp *uop)
         uop->data.vec4[i].u32 = expand32(uop->type, uop->data.vec4[i]);
 }
 
-static int compile(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out)
+static int compile_uops_x86(SwsContext *ctx, const SwsUOpList *uops, SwsCompiledOp *out)
 {
-    const int cpu_flags = av_get_cpu_flags();
-    int ret, mmsize;
-    if (EXTERNAL_AVX512(cpu_flags))
-        mmsize = 64;
-    else if (EXTERNAL_AVX2(cpu_flags))
-        mmsize = 32;
-    else if (EXTERNAL_SSE4(cpu_flags))
-        mmsize = 16;
-    else
-        return AVERROR(ENOTSUP);
-
-    /* Special fast path for in-place packed shuffle */
-    ret = solve_shuffle(ops, mmsize, out);
-    if (ret != AVERROR(ENOTSUP))
-        return ret;
+    int ret, mmsize = get_mmsize();
+    if (mmsize < 0)
+        return mmsize;
 
     SwsOpChain *chain = ff_sws_op_chain_alloc();
     if (!chain)
         return AVERROR(ENOMEM);
 
-    SwsUOpList *uops = ff_sws_uop_list_alloc();
-    if (!uops) {
-        ret = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    SwsUOpFlags flags = SWS_UOP_FLAG_MOVE;
-    if (EXTERNAL_FMA3(cpu_flags))
-        flags |= SWS_UOP_FLAG_FMA;
-
-    ret = ff_sws_ops_translate(ctx, ops, flags, uops);
-    if (ret < 0)
-        goto fail;
-
     *out = (SwsCompiledOp) {
         /* Use at most two full YMM regs during the widest precision section */
         .block_size  = 2 * FFMIN(mmsize, 32) / uops->pixel_size_max,
@@ -649,18 +640,47 @@ static int compile(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out)
     out->cpu_flags = chain->cpu_flags;
     memcpy(out->over_read,  chain->over_read,  sizeof(out->over_read));
     memcpy(out->over_write, chain->over_write, sizeof(out->over_write));
-    ff_sws_uop_list_free(&uops);
     return 0;
 
 fail:
-    ff_sws_uop_list_free(&uops);
     ff_sws_op_chain_free(chain);
     return ret;
 }
 
+static int compile_x86(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out)
+{
+    const int cpu_flags = av_get_cpu_flags();
+    if (!EXTERNAL_SSE4(cpu_flags))
+        return AVERROR(ENOTSUP);
+
+    SwsUOpFlags flags = SWS_UOP_FLAG_MOVE;
+    if (EXTERNAL_FMA3(cpu_flags))
+        flags |= SWS_UOP_FLAG_FMA;
+
+    /* Special fast path for in-place packed shuffle */
+    int ret = solve_shuffle(ops, out);
+    if (ret != AVERROR(ENOTSUP))
+        return ret;
+
+    SwsUOpList *uops = ff_sws_uop_list_alloc();
+    if (!uops)
+        return AVERROR(ENOMEM);
+
+    ret = ff_sws_ops_translate(ctx, ops, flags, uops);
+    if (ret < 0)
+        goto fail;
+
+    ret = compile_uops_x86(ctx, uops, out);
+
+fail:
+    ff_sws_uop_list_free(&uops);
+    return ret;
+}
+
 const SwsOpBackend backend_x86 = {
-    .name       = "x86",
-    .flags      = SWS_BACKEND_X86,
-    .compile    = compile,
-    .hw_format  = AV_PIX_FMT_NONE,
+    .name           = "x86",
+    .flags          = SWS_BACKEND_X86,
+    .compile        = compile_x86,
+    .compile_uops   = compile_uops_x86,
+    .hw_format      = AV_PIX_FMT_NONE,
 };
-- 
2.52.0


>From 2be98a40751722b983d205552646e59eae9856f5 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Tue, 7 Jul 2026 14:17:28 +0200
Subject: [PATCH 07/10] swscale/x86/ops: add micro-op dump to
 compile_uops_x86() as well

This was only done in compile_uops_c(). Add it here as well for consistency.
Long-term I want to move this code to ops_dispatch.c, but that requires
moving the packed shuffle solver there as well, which is still WIP.

Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/x86/ops.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/libswscale/x86/ops.c b/libswscale/x86/ops.c
index b3e0222bb0..8312bf6d07 100644
--- a/libswscale/x86/ops.c
+++ b/libswscale/x86/ops.c
@@ -640,6 +640,14 @@ static int compile_uops_x86(SwsContext *ctx, const SwsUOpList *uops, SwsCompiled
     out->cpu_flags = chain->cpu_flags;
     memcpy(out->over_read,  chain->over_read,  sizeof(out->over_read));
     memcpy(out->over_write, chain->over_write, sizeof(out->over_write));
+
+    av_log(ctx, AV_LOG_DEBUG, "Compiled micro-ops:\n");
+    for (int i = 0; i < uops->num_ops; i++) {
+        char name[SWS_UOP_NAME_MAX];
+        ff_sws_uop_name(&uops->ops[i], name);
+        av_log(ctx, AV_LOG_DEBUG, "    %s\n", name);
+    }
+
     return 0;
 
 fail:
-- 
2.52.0


>From a3a64c58456d8d10ad2f01cb44146d236c8bdb02 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Wed, 8 Jul 2026 00:53:09 +0200
Subject: [PATCH 08/10] swscale/uops: consolidate SWS_UOP_{PERMUTE,COPY,MOVE}

Rather than having two uops for the C reference code and a separate
uop for the x86 backend, we can just implement the C reference
using the same register-register assignment logic.

This results in basically identical codegen, since the compiler is
smart enough to eliminate the unnecessary copies.

On platforms like x86, we still don't care about the PERMUTE vs
COPY distinction, but it's also harmless (2-3 extra lines to
instantiate the underlying MOVE macro on both uop variants).

The op lists change to reflect the new representation, e.g.:

 rgb24 16x16 -> bgr24 16x16:
   [ u8 +++X] SWS_OP_READ         : 3 elem(s) packed >> 0
     min: {0 0 0 _}, max: {255 255 255 _}
   [ u8 +++X] SWS_OP_SWIZZLE      : 2103
     min: {0 0 0 _}, max: {255 255 255 _}
   [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) packed >> 0
     ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)
  translated micro-ops:
     u8_read_packed_xyz
-    u8_permute_zyxw
+    u8_permute_txz_xzt
     u8_write_packed_xyz

Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/uops.c                |  77 +----
 libswscale/uops.h                |  15 +-
 libswscale/uops_list.h           |   1 -
 libswscale/uops_macros.h         | 470 ++++++++++++-------------------
 libswscale/uops_macros_gen.c     |  12 +-
 libswscale/uops_tmpl.c           |  66 +++--
 libswscale/x86/ops.c             |   8 +-
 libswscale/x86/ops_int.asm       |   3 +-
 libswscale/x86/uops_macros.asm.h |   3 +-
 tests/checkasm/sw_ops.c          |  10 +-
 tests/ref/fate/sws-ops-list      |   2 +-
 11 files changed, 247 insertions(+), 420 deletions(-)

diff --git a/libswscale/uops.c b/libswscale/uops.c
index 2c9916d4ed..34369fc301 100644
--- a/libswscale/uops.c
+++ b/libswscale/uops.c
@@ -102,18 +102,7 @@ void ff_sws_uop_name(const SwsUOp *op, char buf[SWS_UOP_NAME_MAX])
         av_bprintf(&bp, "_%u", par->shift.amount);
         break;
     case SWS_UOP_PERMUTE:
-        av_bprint_chars(&bp, '_', 1);
-        for (int i = 0; i < 4; i++)
-            av_bprint_chars(&bp, "xyzw"[par->swizzle.in[i]], 1);
-        break;
     case SWS_UOP_COPY:
-        av_bprint_chars(&bp, '_', 1);
-        for (int i = 0; i < 4; i++) {
-            if (SWS_COMP_TEST(op->mask, i))
-                av_bprint_chars(&bp, "xyzw"[par->swizzle.in[i]], 1);
-        }
-        break;
-    case SWS_UOP_MOVE:
         av_bprint_chars(&bp, '_', 1);
         for (int i = 0; i < par->move.num_moves; i++)
             av_bprint_chars(&bp, "txyzw"[par->move.dst[i] + 1], 1);
@@ -351,10 +340,10 @@ static int count_idx(const int *arr, size_t size, int val)
     return num;
 }
 
-static int translate_move(SwsUOpList *ops, const SwsOp *op)
+static int translate_swizzle(SwsUOpList *ops, const SwsOp *op)
 {
     SwsUOp uop = {
-        .uop  = SWS_UOP_MOVE,
+        .uop  = SWS_UOP_PERMUTE,
         .type = pixel_type_to_int(op->type),
     };
     SwsMoveUOp *par = &uop.par.move;
@@ -419,62 +408,16 @@ static int translate_move(SwsUOpList *ops, const SwsOp *op)
         idx[dst] = idx[src];
     }
 
-    return ff_sws_uop_list_append(ops, &uop);
-}
-
-static int translate_swizzle(SwsUOpList *ops, SwsUOpFlags flags, const SwsOp *op)
-{
-    if (flags & SWS_UOP_FLAG_MOVE)
-        return translate_move(ops, op);
-
-    SwsUOp uop = {
-        .type = pixel_type_to_int(op->type),
-        .uop  = SWS_UOP_PERMUTE,
-        .par.swizzle.in = {0, 1, 2, 3},
-    };
-
-    SwsCompMask needed = ff_sws_comp_mask_needed(op);
+    /* Check for duplicates in the final register map */
     SwsCompMask seen = 0;
     for (int i = 0; i < 4; i++) {
-        if (!SWS_COMP_TEST(needed, i))
-            continue;
-        const int src = op->swizzle.in[i];
-        if (SWS_COMP_TEST(seen, src))
-            uop.uop = SWS_UOP_COPY; /* Swizzle mask contains duplicates */
-        seen |= SWS_COMP(src);
-        uop.par.swizzle.in[i] = src;
-    }
-
-    if (uop.uop == SWS_UOP_PERMUTE) {
-        /* Prevent overlap by moving unused components to unseen indices */
-        for (int i = 0; i < 4; i++) {
-            if (SWS_COMP_TEST(needed, i))
-                continue;
-
-            /* Prefer identity mapping if possible */
-            int unused = i;
-            if (SWS_COMP_TEST(seen, i)) {
-                for (int j = 0; j < 4; j++) {
-                    if (!SWS_COMP_TEST(seen, j)) {
-                        unused = j;
-                        break;
-                    }
-                }
-            }
-
-            uop.par.swizzle.in[i] = unused;
-            seen |= SWS_COMP(unused);
+        av_assert2(idx[i] >= 0); /* should be no tmp register */
+        const SwsCompMask bit = SWS_COMP(idx[i]);
+        if (seen & bit) {
+            uop.uop = SWS_UOP_COPY;
+            break;
         }
-    }
-
-    if (uop.uop == SWS_UOP_COPY) {
-        /* Remove remaining trivial / identity components from the mask */
-        for (int i = 0; i < 4; i++) {
-            if (uop.par.swizzle.in[i] == i)
-                needed &= ~SWS_COMP(i);
-        }
-
-        uop.mask = needed;
+        seen |= bit;
     }
 
     return ff_sws_uop_list_append(ops, &uop);
@@ -597,7 +540,7 @@ static int translate_op(SwsContext *ctx, SwsUOpList *uops, SwsUOpFlags flags,
     case SWS_OP_WRITE:
         return translate_rw_op(ctx, uops, flags, op);
     case SWS_OP_SWIZZLE:
-        return translate_swizzle(uops, flags, op);
+        return translate_swizzle(uops, op);
     case SWS_OP_DITHER:
         return translate_dither_op(uops, op);
     case SWS_OP_LINEAR:
diff --git a/libswscale/uops.h b/libswscale/uops.h
index bea017268a..3c83941e10 100644
--- a/libswscale/uops.h
+++ b/libswscale/uops.h
@@ -95,7 +95,6 @@ typedef uint32_t SwsUOpFlags;
 typedef enum SwsUOpFlagBits {
     SWS_UOP_FLAG_NONE = 0,
     SWS_UOP_FLAG_FMA  = (1 << 0), /* platform supports FMA ops */
-    SWS_UOP_FLAG_MOVE = (1 << 1), /* platform supports SWS_UOP_MOVE */
 } SwsUOpFlagBits;
 
 typedef enum SwsUOpType {
@@ -116,10 +115,9 @@ typedef enum SwsUOpType {
     SWS_UOP_WRITE_NIBBLE,    /* fractional write (4 bits) to single plane */
     SWS_UOP_WRITE_BIT,       /* fractional write (1 bit) to single plane */
 
-    /* Data rearrangement uops; mask = non-trivial and needed components */
-    SWS_UOP_PERMUTE,         /* rearrange components (no duplicates) */
-    SWS_UOP_COPY,            /* copy/duplicate components */
-    SWS_UOP_MOVE,            /* series of register-register assignments */
+    /* Data rearrangement uops; mask is unused */
+    SWS_UOP_PERMUTE,         /* permute pointers (no duplicates) */
+    SWS_UOP_COPY,            /* permute data (may contain duplicates) */
 
     /* Data conversion / manipulation uops; mask = affected components */
     SWS_UOP_SWAP_BYTES,      /* swap byte order in components */
@@ -159,10 +157,6 @@ typedef struct SwsShiftUOp {
     uint8_t amount;
 } SwsShiftUOp;
 
-typedef struct SwsSwizzleUOp {
-    uint8_t in[4]; /* input component for each output component */
-} SwsSwizzleUOp;
-
 typedef struct SwsMoveUOp {
     /* The worst case number of moves (for two independent cycles) */
     #define SWS_UOP_MOVE_MAX 6
@@ -210,8 +204,7 @@ int ff_sws_dither_height(const SwsDitherUOp *dither);
 typedef union SwsUOpParams {
     SwsFilterUOp    filter; /* for SWS_UOP_READ_*_FV/FH */
     SwsShiftUOp     shift;
-    SwsSwizzleUOp   swizzle;
-    SwsMoveUOp      move;
+    SwsMoveUOp      move; /* for SWS_UOP_PERMUTE and SWS_UOP_COPY */
     SwsPackUOp      pack;
     SwsClearUOp     clear;
     SwsLinearUOp    lin;
diff --git a/libswscale/uops_list.h b/libswscale/uops_list.h
index 793678b1d3..047ead2750 100644
--- a/libswscale/uops_list.h
+++ b/libswscale/uops_list.h
@@ -36,7 +36,6 @@
     ENTRY(SWS_UOP_WRITE_BIT,            "write_bit")                 \
     ENTRY(SWS_UOP_PERMUTE,              "permute")                   \
     ENTRY(SWS_UOP_COPY,                 "copy")                      \
-    ENTRY(SWS_UOP_MOVE,                 "move")                      \
     ENTRY(SWS_UOP_SWAP_BYTES,           "swap_bytes")                \
     ENTRY(SWS_UOP_EXPAND_BIT,           "expand_bit")                \
     ENTRY(SWS_UOP_EXPAND_PAIR,          "expand_pair")               \
diff --git a/libswscale/uops_macros.h b/libswscale/uops_macros.h
index a382988361..174cdf297f 100644
--- a/libswscale/uops_macros.h
+++ b/libswscale/uops_macros.h
@@ -106,119 +106,75 @@
 #define SWS_FOR_STRUCT_U8_WRITE_BIT(MACRO, ...) \
     MACRO(__VA_ARGS__, u8_write_bit_x                          , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_WRITE_BIT       , .mask = 0x1)
 #define SWS_FOR_U8_PERMUTE(MACRO, ...) \
-    MACRO(__VA_ARGS__, u8_permute_xzyw                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 0, 2, 1, 3) \
-    MACRO(__VA_ARGS__, u8_permute_xzwy                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 0, 2, 3, 1) \
-    MACRO(__VA_ARGS__, u8_permute_xwzy                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 0, 3, 2, 1) \
-    MACRO(__VA_ARGS__, u8_permute_yxzw                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 1, 0, 2, 3) \
-    MACRO(__VA_ARGS__, u8_permute_yzxw                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 1, 2, 0, 3) \
-    MACRO(__VA_ARGS__, u8_permute_yzwx                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 1, 2, 3, 0) \
-    MACRO(__VA_ARGS__, u8_permute_ywzx                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 1, 3, 2, 0) \
-    MACRO(__VA_ARGS__, u8_permute_zxyw                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 2, 0, 1, 3) \
-    MACRO(__VA_ARGS__, u8_permute_zyxw                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 2, 1, 0, 3) \
-    MACRO(__VA_ARGS__, u8_permute_zywx                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 2, 1, 3, 0) \
-    MACRO(__VA_ARGS__, u8_permute_zwxy                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 2, 3, 0, 1) \
-    MACRO(__VA_ARGS__, u8_permute_wxyz                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 3, 0, 1, 2) \
-    MACRO(__VA_ARGS__, u8_permute_wxzy                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 3, 0, 2, 1) \
-    MACRO(__VA_ARGS__, u8_permute_wyxz                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 3, 1, 0, 2) \
-    MACRO(__VA_ARGS__, u8_permute_wyzx                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 3, 1, 2, 0) \
-    MACRO(__VA_ARGS__, u8_permute_wzxy                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 3, 2, 0, 1) \
-    MACRO(__VA_ARGS__, u8_permute_wzyx                         , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 3, 2, 1, 0)
+    MACRO(__VA_ARGS__, u8_permute_txy_xyt                      , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 3, -1, 0, 1, 0, 0, 0, 0, 1, -1, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_permute_txz_xzt                      , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 3, -1, 0, 2, 0, 0, 0, 0, 2, -1, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_permute_tyz_yzt                      , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 3, -1, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_permute_tyw_ywt                      , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 3, -1, 1, 3, 0, 0, 0, 1, 3, -1, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_permute_txyz_xyzt                    , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 4, -1, 0, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0) \
+    MACRO(__VA_ARGS__, u8_permute_txzy_xzyt                    , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 4, -1, 0, 2, 1, 0, 0, 0, 2, 1, -1, 0, 0) \
+    MACRO(__VA_ARGS__, u8_permute_txzw_xzwt                    , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 4, -1, 0, 2, 3, 0, 0, 0, 2, 3, -1, 0, 0) \
+    MACRO(__VA_ARGS__, u8_permute_txwz_xwzt                    , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 4, -1, 0, 3, 2, 0, 0, 0, 3, 2, -1, 0, 0) \
+    MACRO(__VA_ARGS__, u8_permute_tyzw_yzwt                    , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 4, -1, 1, 2, 3, 0, 0, 1, 2, 3, -1, 0, 0) \
+    MACRO(__VA_ARGS__, u8_permute_txyzw_xyzwt                  , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 5, -1, 0, 1, 2, 3, 0, 0, 1, 2, 3, -1, 0) \
+    MACRO(__VA_ARGS__, u8_permute_txwyz_xwyzt                  , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 5, -1, 0, 3, 1, 2, 0, 0, 3, 1, 2, -1, 0) \
+    MACRO(__VA_ARGS__, u8_permute_txwzy_xwzyt                  , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 5, -1, 0, 3, 2, 1, 0, 0, 3, 2, 1, -1, 0) \
+    MACRO(__VA_ARGS__, u8_permute_txwtyz_xwtyzt                , SWS_PIXEL_U8 , SWS_UOP_PERMUTE         , 0x0, 6, -1, 0, 3, -1, 1, 2, 0, 3, -1, 1, 2, -1)
 #define SWS_FOR_STRUCT_U8_PERMUTE(MACRO, ...) \
-    MACRO(__VA_ARGS__, u8_permute_xzyw                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {0, 2, 1, 3}) \
-    MACRO(__VA_ARGS__, u8_permute_xzwy                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {0, 2, 3, 1}) \
-    MACRO(__VA_ARGS__, u8_permute_xwzy                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {0, 3, 2, 1}) \
-    MACRO(__VA_ARGS__, u8_permute_yxzw                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {1, 0, 2, 3}) \
-    MACRO(__VA_ARGS__, u8_permute_yzxw                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {1, 2, 0, 3}) \
-    MACRO(__VA_ARGS__, u8_permute_yzwx                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {1, 2, 3, 0}) \
-    MACRO(__VA_ARGS__, u8_permute_ywzx                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {1, 3, 2, 0}) \
-    MACRO(__VA_ARGS__, u8_permute_zxyw                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {2, 0, 1, 3}) \
-    MACRO(__VA_ARGS__, u8_permute_zyxw                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {2, 1, 0, 3}) \
-    MACRO(__VA_ARGS__, u8_permute_zywx                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {2, 1, 3, 0}) \
-    MACRO(__VA_ARGS__, u8_permute_zwxy                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {2, 3, 0, 1}) \
-    MACRO(__VA_ARGS__, u8_permute_wxyz                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 0, 1, 2}) \
-    MACRO(__VA_ARGS__, u8_permute_wxzy                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 0, 2, 1}) \
-    MACRO(__VA_ARGS__, u8_permute_wyxz                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 1, 0, 2}) \
-    MACRO(__VA_ARGS__, u8_permute_wyzx                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 1, 2, 0}) \
-    MACRO(__VA_ARGS__, u8_permute_wzxy                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 2, 0, 1}) \
-    MACRO(__VA_ARGS__, u8_permute_wzyx                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 2, 1, 0})
+    MACRO(__VA_ARGS__, u8_permute_txy_xyt                      , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 0, 1, 0, 0, 0}, .par.move.src = {0, 1, -1, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_permute_txz_xzt                      , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 0, 2, 0, 0, 0}, .par.move.src = {0, 2, -1, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_permute_tyz_yzt                      , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 1, 2, 0, 0, 0}, .par.move.src = {1, 2, -1, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_permute_tyw_ywt                      , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 1, 3, 0, 0, 0}, .par.move.src = {1, 3, -1, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_permute_txyz_xyzt                    , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 1, 2, 0, 0}, .par.move.src = {0, 1, 2, -1, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_permute_txzy_xzyt                    , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 2, 1, 0, 0}, .par.move.src = {0, 2, 1, -1, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_permute_txzw_xzwt                    , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 2, 3, 0, 0}, .par.move.src = {0, 2, 3, -1, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_permute_txwz_xwzt                    , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 3, 2, 0, 0}, .par.move.src = {0, 3, 2, -1, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_permute_tyzw_yzwt                    , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 1, 2, 3, 0, 0}, .par.move.src = {1, 2, 3, -1, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_permute_txyzw_xyzwt                  , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 1, 2, 3, 0}, .par.move.src = {0, 1, 2, 3, -1, 0}) \
+    MACRO(__VA_ARGS__, u8_permute_txwyz_xwyzt                  , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 3, 1, 2, 0}, .par.move.src = {0, 3, 1, 2, -1, 0}) \
+    MACRO(__VA_ARGS__, u8_permute_txwzy_xwzyt                  , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 3, 2, 1, 0}, .par.move.src = {0, 3, 2, 1, -1, 0}) \
+    MACRO(__VA_ARGS__, u8_permute_txwtyz_xwtyzt                , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 6, .par.move.dst = {-1, 0, 3, -1, 1, 2}, .par.move.src = {0, 3, -1, 1, 2, -1})
 #define SWS_FOR_U8_COPY(MACRO, ...) \
-    MACRO(__VA_ARGS__, u8_copy_yz_xx                           , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x6, 0, 0, 0, 3) \
-    MACRO(__VA_ARGS__, u8_copy_yzw_xxx                         , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0xe, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_copy_yzw_xxy                         , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0xe, 0, 0, 0, 1) \
-    MACRO(__VA_ARGS__, u8_copy_xyzw_yxxx                       , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0xf, 1, 0, 0, 0)
+    MACRO(__VA_ARGS__, u8_copy_x_y                             , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_x_z                             , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_x_w                             , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_y_x                             , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_y_w                             , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 1, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_z_x                             , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_w_x                             , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_xy_yw                           , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 2, 0, 1, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_xy_zw                           , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 2, 0, 1, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_yx_xw                           , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 2, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_yz_xx                           , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_wz_zx                           , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 2, 3, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_xyz_yzw                         , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 3, 0, 1, 2, 0, 0, 0, 1, 2, 3, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_yzw_xxx                         , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 3, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_zwy_xyx                         , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 3, 2, 3, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_wyz_yzx                         , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 3, 3, 1, 2, 0, 0, 0, 1, 2, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_wzy_zyx                         , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 3, 3, 2, 1, 0, 0, 0, 2, 1, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_xtyz_wyzt                       , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 4, 0, -1, 1, 2, 0, 0, 3, 1, 2, -1, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_zxyw_xyzz                       , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 4, 2, 0, 1, 3, 0, 0, 0, 1, 2, 2, 0, 0) \
+    MACRO(__VA_ARGS__, u8_copy_wtyz_xyzt                       , SWS_PIXEL_U8 , SWS_UOP_COPY            , 0x0, 4, 3, -1, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0)
 #define SWS_FOR_STRUCT_U8_COPY(MACRO, ...) \
-    MACRO(__VA_ARGS__, u8_copy_yz_xx                           , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x6, .par.swizzle.in = {0, 0, 0, 3}) \
-    MACRO(__VA_ARGS__, u8_copy_yzw_xxx                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0xe, .par.swizzle.in = {0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_copy_yzw_xxy                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0xe, .par.swizzle.in = {0, 0, 0, 1}) \
-    MACRO(__VA_ARGS__, u8_copy_xyzw_yxxx                       , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0xf, .par.swizzle.in = {1, 0, 0, 0})
-#define SWS_FOR_U8_MOVE(MACRO, ...) \
-    MACRO(__VA_ARGS__, u8_move_x_y                             , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_x_z                             , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_x_w                             , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_y_x                             , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_y_w                             , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 1, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_z_x                             , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_w_x                             , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_xy_yw                           , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 2, 0, 1, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_xy_zw                           , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 2, 0, 1, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_yx_xw                           , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 2, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_yz_xx                           , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_wz_zx                           , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 2, 3, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_xyz_yzw                         , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 3, 0, 1, 2, 0, 0, 0, 1, 2, 3, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_yzw_xxx                         , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 3, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_zwy_xyx                         , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 3, 2, 3, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_wyz_yzx                         , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 3, 3, 1, 2, 0, 0, 0, 1, 2, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_wzy_zyx                         , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 3, 3, 2, 1, 0, 0, 0, 2, 1, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_txy_xyt                         , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 3, -1, 0, 1, 0, 0, 0, 0, 1, -1, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_txz_xzt                         , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 3, -1, 0, 2, 0, 0, 0, 0, 2, -1, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_tyz_yzt                         , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 3, -1, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_tyw_ywt                         , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 3, -1, 1, 3, 0, 0, 0, 1, 3, -1, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_xtyz_wyzt                       , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 4, 0, -1, 1, 2, 0, 0, 3, 1, 2, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_zxyw_xyzz                       , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 4, 2, 0, 1, 3, 0, 0, 0, 1, 2, 2, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_wtyz_xyzt                       , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 4, 3, -1, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_txyz_xyzt                       , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 4, -1, 0, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_txzy_xzyt                       , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 4, -1, 0, 2, 1, 0, 0, 0, 2, 1, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_txzw_xzwt                       , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 4, -1, 0, 2, 3, 0, 0, 0, 2, 3, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_txwz_xwzt                       , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 4, -1, 0, 3, 2, 0, 0, 0, 3, 2, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_tyzw_yzwt                       , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 4, -1, 1, 2, 3, 0, 0, 1, 2, 3, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u8_move_txyzw_xyzwt                     , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 5, -1, 0, 1, 2, 3, 0, 0, 1, 2, 3, -1, 0) \
-    MACRO(__VA_ARGS__, u8_move_txwyz_xwyzt                     , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 5, -1, 0, 3, 1, 2, 0, 0, 3, 1, 2, -1, 0) \
-    MACRO(__VA_ARGS__, u8_move_txwzy_xwzyt                     , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 5, -1, 0, 3, 2, 1, 0, 0, 3, 2, 1, -1, 0) \
-    MACRO(__VA_ARGS__, u8_move_txwtyz_xwtyzt                   , SWS_PIXEL_U8 , SWS_UOP_MOVE            , 0x0, 6, -1, 0, 3, -1, 1, 2, 0, 3, -1, 1, 2, -1)
-#define SWS_FOR_STRUCT_U8_MOVE(MACRO, ...) \
-    MACRO(__VA_ARGS__, u8_move_x_y                             , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {1, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_x_z                             , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {2, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_x_w                             , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {3, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_y_x                             , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_y_w                             , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {3, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_z_x                             , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {2, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_w_x                             , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {3, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_xy_yw                           , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {0, 1, 0, 0, 0, 0}, .par.move.src = {1, 3, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_xy_zw                           , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {0, 1, 0, 0, 0, 0}, .par.move.src = {2, 3, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_yx_xw                           , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {0, 3, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_yz_xx                           , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {1, 2, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_wz_zx                           , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {3, 2, 0, 0, 0, 0}, .par.move.src = {2, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_xyz_yzw                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {0, 1, 2, 0, 0, 0}, .par.move.src = {1, 2, 3, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_yzw_xxx                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {1, 2, 3, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_zwy_xyx                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {2, 3, 1, 0, 0, 0}, .par.move.src = {0, 1, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_wyz_yzx                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {3, 1, 2, 0, 0, 0}, .par.move.src = {1, 2, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_wzy_zyx                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {3, 2, 1, 0, 0, 0}, .par.move.src = {2, 1, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_txy_xyt                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 0, 1, 0, 0, 0}, .par.move.src = {0, 1, -1, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_txz_xzt                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 0, 2, 0, 0, 0}, .par.move.src = {0, 2, -1, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_tyz_yzt                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 1, 2, 0, 0, 0}, .par.move.src = {1, 2, -1, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_tyw_ywt                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 1, 3, 0, 0, 0}, .par.move.src = {1, 3, -1, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_xtyz_wyzt                       , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {0, -1, 1, 2, 0, 0}, .par.move.src = {3, 1, 2, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_zxyw_xyzz                       , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {2, 0, 1, 3, 0, 0}, .par.move.src = {0, 1, 2, 2, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_wtyz_xyzt                       , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {3, -1, 1, 2, 0, 0}, .par.move.src = {0, 1, 2, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_txyz_xyzt                       , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 1, 2, 0, 0}, .par.move.src = {0, 1, 2, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_txzy_xzyt                       , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 2, 1, 0, 0}, .par.move.src = {0, 2, 1, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_txzw_xzwt                       , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 2, 3, 0, 0}, .par.move.src = {0, 2, 3, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_txwz_xwzt                       , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 3, 2, 0, 0}, .par.move.src = {0, 3, 2, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_tyzw_yzwt                       , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 1, 2, 3, 0, 0}, .par.move.src = {1, 2, 3, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u8_move_txyzw_xyzwt                     , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 1, 2, 3, 0}, .par.move.src = {0, 1, 2, 3, -1, 0}) \
-    MACRO(__VA_ARGS__, u8_move_txwyz_xwyzt                     , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 3, 1, 2, 0}, .par.move.src = {0, 3, 1, 2, -1, 0}) \
-    MACRO(__VA_ARGS__, u8_move_txwzy_xwzyt                     , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 3, 2, 1, 0}, .par.move.src = {0, 3, 2, 1, -1, 0}) \
-    MACRO(__VA_ARGS__, u8_move_txwtyz_xwtyzt                   , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 6, .par.move.dst = {-1, 0, 3, -1, 1, 2}, .par.move.src = {0, 3, -1, 1, 2, -1})
+    MACRO(__VA_ARGS__, u8_copy_x_y                             , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {1, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_x_z                             , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {2, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_x_w                             , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {3, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_y_x                             , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_y_w                             , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {3, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_z_x                             , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {2, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_w_x                             , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {3, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_xy_yw                           , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {0, 1, 0, 0, 0, 0}, .par.move.src = {1, 3, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_xy_zw                           , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {0, 1, 0, 0, 0, 0}, .par.move.src = {2, 3, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_yx_xw                           , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {0, 3, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_yz_xx                           , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {1, 2, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_wz_zx                           , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {3, 2, 0, 0, 0, 0}, .par.move.src = {2, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_xyz_yzw                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {0, 1, 2, 0, 0, 0}, .par.move.src = {1, 2, 3, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_yzw_xxx                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {1, 2, 3, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_zwy_xyx                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {2, 3, 1, 0, 0, 0}, .par.move.src = {0, 1, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_wyz_yzx                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {3, 1, 2, 0, 0, 0}, .par.move.src = {1, 2, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_wzy_zyx                         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {3, 2, 1, 0, 0, 0}, .par.move.src = {2, 1, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_xtyz_wyzt                       , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {0, -1, 1, 2, 0, 0}, .par.move.src = {3, 1, 2, -1, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_zxyw_xyzz                       , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {2, 0, 1, 3, 0, 0}, .par.move.src = {0, 1, 2, 2, 0, 0}) \
+    MACRO(__VA_ARGS__, u8_copy_wtyz_xyzt                       , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {3, -1, 1, 2, 0, 0}, .par.move.src = {0, 1, 2, -1, 0, 0})
 #define SWS_FOR_U8_SWAP_BYTES(MACRO, ...)
 #define SWS_FOR_STRUCT_U8_SWAP_BYTES(MACRO, ...)
 #define SWS_FOR_U8_EXPAND_BIT(MACRO, ...) \
@@ -418,87 +374,55 @@
 #define SWS_FOR_U16_WRITE_BIT(MACRO, ...)
 #define SWS_FOR_STRUCT_U16_WRITE_BIT(MACRO, ...)
 #define SWS_FOR_U16_PERMUTE(MACRO, ...) \
-    MACRO(__VA_ARGS__, u16_permute_xzwy                        , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 0, 2, 3, 1) \
-    MACRO(__VA_ARGS__, u16_permute_xwzy                        , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 0, 3, 2, 1) \
-    MACRO(__VA_ARGS__, u16_permute_yxzw                        , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 1, 0, 2, 3) \
-    MACRO(__VA_ARGS__, u16_permute_yzxw                        , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 1, 2, 0, 3) \
-    MACRO(__VA_ARGS__, u16_permute_yzwx                        , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 1, 2, 3, 0) \
-    MACRO(__VA_ARGS__, u16_permute_zxyw                        , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 2, 0, 1, 3) \
-    MACRO(__VA_ARGS__, u16_permute_zyxw                        , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 2, 1, 0, 3) \
-    MACRO(__VA_ARGS__, u16_permute_zywx                        , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 2, 1, 3, 0) \
-    MACRO(__VA_ARGS__, u16_permute_wxyz                        , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 3, 0, 1, 2) \
-    MACRO(__VA_ARGS__, u16_permute_wxzy                        , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 3, 0, 2, 1) \
-    MACRO(__VA_ARGS__, u16_permute_wyxz                        , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 3, 1, 0, 2) \
-    MACRO(__VA_ARGS__, u16_permute_wyzx                        , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 3, 1, 2, 0) \
-    MACRO(__VA_ARGS__, u16_permute_wzyx                        , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 3, 2, 1, 0)
+    MACRO(__VA_ARGS__, u16_permute_txy_xyt                     , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 3, -1, 0, 1, 0, 0, 0, 0, 1, -1, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u16_permute_txz_xzt                     , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 3, -1, 0, 2, 0, 0, 0, 0, 2, -1, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u16_permute_txyz_xyzt                   , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 4, -1, 0, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0) \
+    MACRO(__VA_ARGS__, u16_permute_txzy_xzyt                   , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 4, -1, 0, 2, 1, 0, 0, 0, 2, 1, -1, 0, 0) \
+    MACRO(__VA_ARGS__, u16_permute_tyzw_yzwt                   , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 4, -1, 1, 2, 3, 0, 0, 1, 2, 3, -1, 0, 0) \
+    MACRO(__VA_ARGS__, u16_permute_txyzw_xyzwt                 , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 5, -1, 0, 1, 2, 3, 0, 0, 1, 2, 3, -1, 0) \
+    MACRO(__VA_ARGS__, u16_permute_txwzy_xwzyt                 , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 5, -1, 0, 3, 2, 1, 0, 0, 3, 2, 1, -1, 0) \
+    MACRO(__VA_ARGS__, u16_permute_txwtyz_xwtyzt               , SWS_PIXEL_U16, SWS_UOP_PERMUTE         , 0x0, 6, -1, 0, 3, -1, 1, 2, 0, 3, -1, 1, 2, -1)
 #define SWS_FOR_STRUCT_U16_PERMUTE(MACRO, ...) \
-    MACRO(__VA_ARGS__, u16_permute_xzwy                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {0, 2, 3, 1}) \
-    MACRO(__VA_ARGS__, u16_permute_xwzy                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {0, 3, 2, 1}) \
-    MACRO(__VA_ARGS__, u16_permute_yxzw                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {1, 0, 2, 3}) \
-    MACRO(__VA_ARGS__, u16_permute_yzxw                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {1, 2, 0, 3}) \
-    MACRO(__VA_ARGS__, u16_permute_yzwx                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {1, 2, 3, 0}) \
-    MACRO(__VA_ARGS__, u16_permute_zxyw                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {2, 0, 1, 3}) \
-    MACRO(__VA_ARGS__, u16_permute_zyxw                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {2, 1, 0, 3}) \
-    MACRO(__VA_ARGS__, u16_permute_zywx                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {2, 1, 3, 0}) \
-    MACRO(__VA_ARGS__, u16_permute_wxyz                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 0, 1, 2}) \
-    MACRO(__VA_ARGS__, u16_permute_wxzy                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 0, 2, 1}) \
-    MACRO(__VA_ARGS__, u16_permute_wyxz                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 1, 0, 2}) \
-    MACRO(__VA_ARGS__, u16_permute_wyzx                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 1, 2, 0}) \
-    MACRO(__VA_ARGS__, u16_permute_wzyx                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 2, 1, 0})
+    MACRO(__VA_ARGS__, u16_permute_txy_xyt                     , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 0, 1, 0, 0, 0}, .par.move.src = {0, 1, -1, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_permute_txz_xzt                     , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 0, 2, 0, 0, 0}, .par.move.src = {0, 2, -1, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_permute_txyz_xyzt                   , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 1, 2, 0, 0}, .par.move.src = {0, 1, 2, -1, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_permute_txzy_xzyt                   , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 2, 1, 0, 0}, .par.move.src = {0, 2, 1, -1, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_permute_tyzw_yzwt                   , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 1, 2, 3, 0, 0}, .par.move.src = {1, 2, 3, -1, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_permute_txyzw_xyzwt                 , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 1, 2, 3, 0}, .par.move.src = {0, 1, 2, 3, -1, 0}) \
+    MACRO(__VA_ARGS__, u16_permute_txwzy_xwzyt                 , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 3, 2, 1, 0}, .par.move.src = {0, 3, 2, 1, -1, 0}) \
+    MACRO(__VA_ARGS__, u16_permute_txwtyz_xwtyzt               , .type = SWS_PIXEL_U16, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 6, .par.move.dst = {-1, 0, 3, -1, 1, 2}, .par.move.src = {0, 3, -1, 1, 2, -1})
 #define SWS_FOR_U16_COPY(MACRO, ...) \
-    MACRO(__VA_ARGS__, u16_copy_yz_xx                          , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x6, 0, 0, 0, 3) \
-    MACRO(__VA_ARGS__, u16_copy_yzw_xxy                        , SWS_PIXEL_U16, SWS_UOP_COPY            , 0xe, 0, 0, 0, 1)
+    MACRO(__VA_ARGS__, u16_copy_x_y                            , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u16_copy_x_z                            , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u16_copy_x_w                            , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u16_copy_y_x                            , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u16_copy_y_w                            , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x0, 1, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u16_copy_w_x                            , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u16_copy_xz_zw                          , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x0, 2, 0, 2, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u16_copy_yx_xw                          , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x0, 2, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u16_copy_yz_xx                          , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u16_copy_wz_zx                          , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x0, 2, 3, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u16_copy_xyz_yzw                        , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x0, 3, 0, 1, 2, 0, 0, 0, 1, 2, 3, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u16_copy_zwy_xyx                        , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x0, 3, 2, 3, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u16_copy_wzy_zyx                        , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x0, 3, 3, 2, 1, 0, 0, 0, 2, 1, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u16_copy_xtyz_wyzt                      , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x0, 4, 0, -1, 1, 2, 0, 0, 3, 1, 2, -1, 0, 0) \
+    MACRO(__VA_ARGS__, u16_copy_wtyz_xyzt                      , SWS_PIXEL_U16, SWS_UOP_COPY            , 0x0, 4, 3, -1, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0)
 #define SWS_FOR_STRUCT_U16_COPY(MACRO, ...) \
-    MACRO(__VA_ARGS__, u16_copy_yz_xx                          , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x6, .par.swizzle.in = {0, 0, 0, 3}) \
-    MACRO(__VA_ARGS__, u16_copy_yzw_xxy                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0xe, .par.swizzle.in = {0, 0, 0, 1})
-#define SWS_FOR_U16_MOVE(MACRO, ...) \
-    MACRO(__VA_ARGS__, u16_move_x_y                            , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_x_z                            , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_x_w                            , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_y_x                            , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_y_w                            , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 1, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_w_x                            , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_xz_zw                          , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 2, 0, 2, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_yx_xw                          , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 2, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_yz_xx                          , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_wz_zx                          , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 2, 3, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_xyz_yzw                        , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 3, 0, 1, 2, 0, 0, 0, 1, 2, 3, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_zwy_xyx                        , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 3, 2, 3, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_wzy_zyx                        , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 3, 3, 2, 1, 0, 0, 0, 2, 1, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_txy_xyt                        , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 3, -1, 0, 1, 0, 0, 0, 0, 1, -1, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_txz_xzt                        , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 3, -1, 0, 2, 0, 0, 0, 0, 2, -1, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_xtyz_wyzt                      , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 4, 0, -1, 1, 2, 0, 0, 3, 1, 2, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_wtyz_xyzt                      , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 4, 3, -1, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_txyz_xyzt                      , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 4, -1, 0, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_txzy_xzyt                      , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 4, -1, 0, 2, 1, 0, 0, 0, 2, 1, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_tyzw_yzwt                      , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 4, -1, 1, 2, 3, 0, 0, 1, 2, 3, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u16_move_txyzw_xyzwt                    , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 5, -1, 0, 1, 2, 3, 0, 0, 1, 2, 3, -1, 0) \
-    MACRO(__VA_ARGS__, u16_move_txwzy_xwzyt                    , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 5, -1, 0, 3, 2, 1, 0, 0, 3, 2, 1, -1, 0) \
-    MACRO(__VA_ARGS__, u16_move_txwtyz_xwtyzt                  , SWS_PIXEL_U16, SWS_UOP_MOVE            , 0x0, 6, -1, 0, 3, -1, 1, 2, 0, 3, -1, 1, 2, -1)
-#define SWS_FOR_STRUCT_U16_MOVE(MACRO, ...) \
-    MACRO(__VA_ARGS__, u16_move_x_y                            , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {1, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_x_z                            , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {2, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_x_w                            , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {3, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_y_x                            , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_y_w                            , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {3, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_w_x                            , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {3, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_xz_zw                          , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {0, 2, 0, 0, 0, 0}, .par.move.src = {2, 3, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_yx_xw                          , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {0, 3, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_yz_xx                          , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {1, 2, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_wz_zx                          , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {3, 2, 0, 0, 0, 0}, .par.move.src = {2, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_xyz_yzw                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {0, 1, 2, 0, 0, 0}, .par.move.src = {1, 2, 3, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_zwy_xyx                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {2, 3, 1, 0, 0, 0}, .par.move.src = {0, 1, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_wzy_zyx                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {3, 2, 1, 0, 0, 0}, .par.move.src = {2, 1, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_txy_xyt                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 0, 1, 0, 0, 0}, .par.move.src = {0, 1, -1, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_txz_xzt                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 0, 2, 0, 0, 0}, .par.move.src = {0, 2, -1, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_xtyz_wyzt                      , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {0, -1, 1, 2, 0, 0}, .par.move.src = {3, 1, 2, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_wtyz_xyzt                      , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {3, -1, 1, 2, 0, 0}, .par.move.src = {0, 1, 2, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_txyz_xyzt                      , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 1, 2, 0, 0}, .par.move.src = {0, 1, 2, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_txzy_xzyt                      , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 2, 1, 0, 0}, .par.move.src = {0, 2, 1, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_tyzw_yzwt                      , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 1, 2, 3, 0, 0}, .par.move.src = {1, 2, 3, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u16_move_txyzw_xyzwt                    , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 1, 2, 3, 0}, .par.move.src = {0, 1, 2, 3, -1, 0}) \
-    MACRO(__VA_ARGS__, u16_move_txwzy_xwzyt                    , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 3, 2, 1, 0}, .par.move.src = {0, 3, 2, 1, -1, 0}) \
-    MACRO(__VA_ARGS__, u16_move_txwtyz_xwtyzt                  , .type = SWS_PIXEL_U16, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 6, .par.move.dst = {-1, 0, 3, -1, 1, 2}, .par.move.src = {0, 3, -1, 1, 2, -1})
+    MACRO(__VA_ARGS__, u16_copy_x_y                            , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {1, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_copy_x_z                            , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {2, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_copy_x_w                            , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {3, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_copy_y_x                            , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_copy_y_w                            , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {3, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_copy_w_x                            , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {3, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_copy_xz_zw                          , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {0, 2, 0, 0, 0, 0}, .par.move.src = {2, 3, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_copy_yx_xw                          , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {0, 3, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_copy_yz_xx                          , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {1, 2, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_copy_wz_zx                          , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {3, 2, 0, 0, 0, 0}, .par.move.src = {2, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_copy_xyz_yzw                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {0, 1, 2, 0, 0, 0}, .par.move.src = {1, 2, 3, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_copy_zwy_xyx                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {2, 3, 1, 0, 0, 0}, .par.move.src = {0, 1, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_copy_wzy_zyx                        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {3, 2, 1, 0, 0, 0}, .par.move.src = {2, 1, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_copy_xtyz_wyzt                      , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {0, -1, 1, 2, 0, 0}, .par.move.src = {3, 1, 2, -1, 0, 0}) \
+    MACRO(__VA_ARGS__, u16_copy_wtyz_xyzt                      , .type = SWS_PIXEL_U16, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {3, -1, 1, 2, 0, 0}, .par.move.src = {0, 1, 2, -1, 0, 0})
 #define SWS_FOR_U16_SWAP_BYTES(MACRO, ...) \
     MACRO(__VA_ARGS__, u16_swap_bytes_x                        , SWS_PIXEL_U16, SWS_UOP_SWAP_BYTES      , 0x1) \
     MACRO(__VA_ARGS__, u16_swap_bytes_y                        , SWS_PIXEL_U16, SWS_UOP_SWAP_BYTES      , 0x2) \
@@ -706,113 +630,73 @@
 #define SWS_FOR_U32_WRITE_BIT(MACRO, ...)
 #define SWS_FOR_STRUCT_U32_WRITE_BIT(MACRO, ...)
 #define SWS_FOR_U32_PERMUTE(MACRO, ...) \
-    MACRO(__VA_ARGS__, u32_permute_xzyw                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 0, 2, 1, 3) \
-    MACRO(__VA_ARGS__, u32_permute_xzwy                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 0, 2, 3, 1) \
-    MACRO(__VA_ARGS__, u32_permute_xwzy                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 0, 3, 2, 1) \
-    MACRO(__VA_ARGS__, u32_permute_yxzw                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 1, 0, 2, 3) \
-    MACRO(__VA_ARGS__, u32_permute_yzxw                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 1, 2, 0, 3) \
-    MACRO(__VA_ARGS__, u32_permute_yzwx                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 1, 2, 3, 0) \
-    MACRO(__VA_ARGS__, u32_permute_zxyw                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 2, 0, 1, 3) \
-    MACRO(__VA_ARGS__, u32_permute_zyxw                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 2, 1, 0, 3) \
-    MACRO(__VA_ARGS__, u32_permute_zywx                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 2, 1, 3, 0) \
-    MACRO(__VA_ARGS__, u32_permute_zwyx                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 2, 3, 1, 0) \
-    MACRO(__VA_ARGS__, u32_permute_wxyz                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 3, 0, 1, 2) \
-    MACRO(__VA_ARGS__, u32_permute_wxzy                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 3, 0, 2, 1) \
-    MACRO(__VA_ARGS__, u32_permute_wyxz                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 3, 1, 0, 2) \
-    MACRO(__VA_ARGS__, u32_permute_wyzx                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 3, 1, 2, 0) \
-    MACRO(__VA_ARGS__, u32_permute_wzxy                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 3, 2, 0, 1) \
-    MACRO(__VA_ARGS__, u32_permute_wzyx                        , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 3, 2, 1, 0)
+    MACRO(__VA_ARGS__, u32_permute_txy_xyt                     , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 3, -1, 0, 1, 0, 0, 0, 0, 1, -1, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_permute_txz_xzt                     , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 3, -1, 0, 2, 0, 0, 0, 0, 2, -1, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_permute_tyz_yzt                     , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 3, -1, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_permute_tyw_ywt                     , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 3, -1, 1, 3, 0, 0, 0, 1, 3, -1, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_permute_txyz_xyzt                   , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 4, -1, 0, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0) \
+    MACRO(__VA_ARGS__, u32_permute_txzy_xzyt                   , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 4, -1, 0, 2, 1, 0, 0, 0, 2, 1, -1, 0, 0) \
+    MACRO(__VA_ARGS__, u32_permute_txyzw_xyzwt                 , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 5, -1, 0, 1, 2, 3, 0, 0, 1, 2, 3, -1, 0) \
+    MACRO(__VA_ARGS__, u32_permute_txwyz_xwyzt                 , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 5, -1, 0, 3, 1, 2, 0, 0, 3, 1, 2, -1, 0) \
+    MACRO(__VA_ARGS__, u32_permute_txwzy_xwzyt                 , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 5, -1, 0, 3, 2, 1, 0, 0, 3, 2, 1, -1, 0) \
+    MACRO(__VA_ARGS__, u32_permute_txwtyz_xwtyzt               , SWS_PIXEL_U32, SWS_UOP_PERMUTE         , 0x0, 6, -1, 0, 3, -1, 1, 2, 0, 3, -1, 1, 2, -1)
 #define SWS_FOR_STRUCT_U32_PERMUTE(MACRO, ...) \
-    MACRO(__VA_ARGS__, u32_permute_xzyw                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {0, 2, 1, 3}) \
-    MACRO(__VA_ARGS__, u32_permute_xzwy                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {0, 2, 3, 1}) \
-    MACRO(__VA_ARGS__, u32_permute_xwzy                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {0, 3, 2, 1}) \
-    MACRO(__VA_ARGS__, u32_permute_yxzw                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {1, 0, 2, 3}) \
-    MACRO(__VA_ARGS__, u32_permute_yzxw                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {1, 2, 0, 3}) \
-    MACRO(__VA_ARGS__, u32_permute_yzwx                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {1, 2, 3, 0}) \
-    MACRO(__VA_ARGS__, u32_permute_zxyw                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {2, 0, 1, 3}) \
-    MACRO(__VA_ARGS__, u32_permute_zyxw                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {2, 1, 0, 3}) \
-    MACRO(__VA_ARGS__, u32_permute_zywx                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {2, 1, 3, 0}) \
-    MACRO(__VA_ARGS__, u32_permute_zwyx                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {2, 3, 1, 0}) \
-    MACRO(__VA_ARGS__, u32_permute_wxyz                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 0, 1, 2}) \
-    MACRO(__VA_ARGS__, u32_permute_wxzy                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 0, 2, 1}) \
-    MACRO(__VA_ARGS__, u32_permute_wyxz                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 1, 0, 2}) \
-    MACRO(__VA_ARGS__, u32_permute_wyzx                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 1, 2, 0}) \
-    MACRO(__VA_ARGS__, u32_permute_wzxy                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 2, 0, 1}) \
-    MACRO(__VA_ARGS__, u32_permute_wzyx                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.swizzle.in = {3, 2, 1, 0})
+    MACRO(__VA_ARGS__, u32_permute_txy_xyt                     , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 0, 1, 0, 0, 0}, .par.move.src = {0, 1, -1, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_permute_txz_xzt                     , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 0, 2, 0, 0, 0}, .par.move.src = {0, 2, -1, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_permute_tyz_yzt                     , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 1, 2, 0, 0, 0}, .par.move.src = {1, 2, -1, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_permute_tyw_ywt                     , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 1, 3, 0, 0, 0}, .par.move.src = {1, 3, -1, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_permute_txyz_xyzt                   , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 1, 2, 0, 0}, .par.move.src = {0, 1, 2, -1, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_permute_txzy_xzyt                   , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 2, 1, 0, 0}, .par.move.src = {0, 2, 1, -1, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_permute_txyzw_xyzwt                 , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 1, 2, 3, 0}, .par.move.src = {0, 1, 2, 3, -1, 0}) \
+    MACRO(__VA_ARGS__, u32_permute_txwyz_xwyzt                 , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 3, 1, 2, 0}, .par.move.src = {0, 3, 1, 2, -1, 0}) \
+    MACRO(__VA_ARGS__, u32_permute_txwzy_xwzyt                 , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 3, 2, 1, 0}, .par.move.src = {0, 3, 2, 1, -1, 0}) \
+    MACRO(__VA_ARGS__, u32_permute_txwtyz_xwtyzt               , .type = SWS_PIXEL_U32, .uop = SWS_UOP_PERMUTE         , .mask = 0x0, .par.move.num_moves = 6, .par.move.dst = {-1, 0, 3, -1, 1, 2}, .par.move.src = {0, 3, -1, 1, 2, -1})
 #define SWS_FOR_U32_COPY(MACRO, ...) \
-    MACRO(__VA_ARGS__, u32_copy_yz_xx                          , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x6, 0, 0, 0, 3) \
-    MACRO(__VA_ARGS__, u32_copy_yzw_xxx                        , SWS_PIXEL_U32, SWS_UOP_COPY            , 0xe, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_copy_yzw_xxy                        , SWS_PIXEL_U32, SWS_UOP_COPY            , 0xe, 0, 0, 0, 1)
+    MACRO(__VA_ARGS__, u32_copy_x_y                            , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_x_z                            , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_x_w                            , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_y_x                            , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_y_w                            , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 1, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_z_x                            , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_w_x                            , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_w_y                            , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_xz_zw                          , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 2, 0, 2, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_yz_xx                          , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_zx_xw                          , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 2, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_wx_xy                          , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 2, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_wy_yx                          , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 2, 3, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_wz_zx                          , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 2, 3, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_xyz_yzw                        , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 3, 0, 1, 2, 0, 0, 0, 1, 2, 3, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_xzy_zyw                        , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 3, 0, 2, 1, 0, 0, 0, 2, 1, 3, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_yzw_xxx                        , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 3, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_zwy_xyx                        , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 3, 2, 3, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_wyz_yzx                        , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 3, 3, 1, 2, 0, 0, 0, 1, 2, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_wzy_zyx                        , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 3, 3, 2, 1, 0, 0, 0, 2, 1, 0, 0, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_xtyz_wyzt                      , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 4, 0, -1, 1, 2, 0, 0, 3, 1, 2, -1, 0, 0) \
+    MACRO(__VA_ARGS__, u32_copy_wtyz_xyzt                      , SWS_PIXEL_U32, SWS_UOP_COPY            , 0x0, 4, 3, -1, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0)
 #define SWS_FOR_STRUCT_U32_COPY(MACRO, ...) \
-    MACRO(__VA_ARGS__, u32_copy_yz_xx                          , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x6, .par.swizzle.in = {0, 0, 0, 3}) \
-    MACRO(__VA_ARGS__, u32_copy_yzw_xxx                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0xe, .par.swizzle.in = {0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_copy_yzw_xxy                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0xe, .par.swizzle.in = {0, 0, 0, 1})
-#define SWS_FOR_U32_MOVE(MACRO, ...) \
-    MACRO(__VA_ARGS__, u32_move_x_y                            , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_x_z                            , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_x_w                            , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_y_x                            , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_y_w                            , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 1, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_z_x                            , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_w_x                            , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_w_y                            , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_xz_zw                          , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 2, 0, 2, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_yz_xx                          , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_zx_xw                          , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 2, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_wx_xy                          , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 2, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_wy_yx                          , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 2, 3, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_wz_zx                          , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 2, 3, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_xyz_yzw                        , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 3, 0, 1, 2, 0, 0, 0, 1, 2, 3, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_xzy_zyw                        , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 3, 0, 2, 1, 0, 0, 0, 2, 1, 3, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_yzw_xxx                        , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 3, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_zwy_xyx                        , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 3, 2, 3, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_wyz_yzx                        , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 3, 3, 1, 2, 0, 0, 0, 1, 2, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_wzy_zyx                        , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 3, 3, 2, 1, 0, 0, 0, 2, 1, 0, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_txy_xyt                        , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 3, -1, 0, 1, 0, 0, 0, 0, 1, -1, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_txz_xzt                        , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 3, -1, 0, 2, 0, 0, 0, 0, 2, -1, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_tyz_yzt                        , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 3, -1, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_tyw_ywt                        , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 3, -1, 1, 3, 0, 0, 0, 1, 3, -1, 0, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_xtyz_wyzt                      , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 4, 0, -1, 1, 2, 0, 0, 3, 1, 2, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_wtyz_xyzt                      , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 4, 3, -1, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_txyz_xyzt                      , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 4, -1, 0, 1, 2, 0, 0, 0, 1, 2, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_txzy_xzyt                      , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 4, -1, 0, 2, 1, 0, 0, 0, 2, 1, -1, 0, 0) \
-    MACRO(__VA_ARGS__, u32_move_txyzw_xyzwt                    , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 5, -1, 0, 1, 2, 3, 0, 0, 1, 2, 3, -1, 0) \
-    MACRO(__VA_ARGS__, u32_move_txwyz_xwyzt                    , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 5, -1, 0, 3, 1, 2, 0, 0, 3, 1, 2, -1, 0) \
-    MACRO(__VA_ARGS__, u32_move_txwzy_xwzyt                    , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 5, -1, 0, 3, 2, 1, 0, 0, 3, 2, 1, -1, 0) \
-    MACRO(__VA_ARGS__, u32_move_txwtyz_xwtyzt                  , SWS_PIXEL_U32, SWS_UOP_MOVE            , 0x0, 6, -1, 0, 3, -1, 1, 2, 0, 3, -1, 1, 2, -1)
-#define SWS_FOR_STRUCT_U32_MOVE(MACRO, ...) \
-    MACRO(__VA_ARGS__, u32_move_x_y                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {1, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_x_z                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {2, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_x_w                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {3, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_y_x                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_y_w                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {3, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_z_x                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {2, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_w_x                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {3, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_w_y                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {3, 0, 0, 0, 0, 0}, .par.move.src = {1, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_xz_zw                          , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {0, 2, 0, 0, 0, 0}, .par.move.src = {2, 3, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_yz_xx                          , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {1, 2, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_zx_xw                          , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {2, 0, 0, 0, 0, 0}, .par.move.src = {0, 3, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_wx_xy                          , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {3, 0, 0, 0, 0, 0}, .par.move.src = {0, 1, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_wy_yx                          , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {3, 1, 0, 0, 0, 0}, .par.move.src = {1, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_wz_zx                          , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {3, 2, 0, 0, 0, 0}, .par.move.src = {2, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_xyz_yzw                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {0, 1, 2, 0, 0, 0}, .par.move.src = {1, 2, 3, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_xzy_zyw                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {0, 2, 1, 0, 0, 0}, .par.move.src = {2, 1, 3, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_yzw_xxx                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {1, 2, 3, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_zwy_xyx                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {2, 3, 1, 0, 0, 0}, .par.move.src = {0, 1, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_wyz_yzx                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {3, 1, 2, 0, 0, 0}, .par.move.src = {1, 2, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_wzy_zyx                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {3, 2, 1, 0, 0, 0}, .par.move.src = {2, 1, 0, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_txy_xyt                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 0, 1, 0, 0, 0}, .par.move.src = {0, 1, -1, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_txz_xzt                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 0, 2, 0, 0, 0}, .par.move.src = {0, 2, -1, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_tyz_yzt                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 1, 2, 0, 0, 0}, .par.move.src = {1, 2, -1, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_tyw_ywt                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {-1, 1, 3, 0, 0, 0}, .par.move.src = {1, 3, -1, 0, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_xtyz_wyzt                      , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {0, -1, 1, 2, 0, 0}, .par.move.src = {3, 1, 2, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_wtyz_xyzt                      , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {3, -1, 1, 2, 0, 0}, .par.move.src = {0, 1, 2, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_txyz_xyzt                      , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 1, 2, 0, 0}, .par.move.src = {0, 1, 2, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_txzy_xzyt                      , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {-1, 0, 2, 1, 0, 0}, .par.move.src = {0, 2, 1, -1, 0, 0}) \
-    MACRO(__VA_ARGS__, u32_move_txyzw_xyzwt                    , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 1, 2, 3, 0}, .par.move.src = {0, 1, 2, 3, -1, 0}) \
-    MACRO(__VA_ARGS__, u32_move_txwyz_xwyzt                    , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 3, 1, 2, 0}, .par.move.src = {0, 3, 1, 2, -1, 0}) \
-    MACRO(__VA_ARGS__, u32_move_txwzy_xwzyt                    , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 5, .par.move.dst = {-1, 0, 3, 2, 1, 0}, .par.move.src = {0, 3, 2, 1, -1, 0}) \
-    MACRO(__VA_ARGS__, u32_move_txwtyz_xwtyzt                  , .type = SWS_PIXEL_U32, .uop = SWS_UOP_MOVE            , .mask = 0x0, .par.move.num_moves = 6, .par.move.dst = {-1, 0, 3, -1, 1, 2}, .par.move.src = {0, 3, -1, 1, 2, -1})
+    MACRO(__VA_ARGS__, u32_copy_x_y                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {1, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_x_z                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {2, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_x_w                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {0, 0, 0, 0, 0, 0}, .par.move.src = {3, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_y_x                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_y_w                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {1, 0, 0, 0, 0, 0}, .par.move.src = {3, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_z_x                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {2, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_w_x                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {3, 0, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_w_y                            , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 1, .par.move.dst = {3, 0, 0, 0, 0, 0}, .par.move.src = {1, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_xz_zw                          , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {0, 2, 0, 0, 0, 0}, .par.move.src = {2, 3, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_yz_xx                          , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {1, 2, 0, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_zx_xw                          , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {2, 0, 0, 0, 0, 0}, .par.move.src = {0, 3, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_wx_xy                          , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {3, 0, 0, 0, 0, 0}, .par.move.src = {0, 1, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_wy_yx                          , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {3, 1, 0, 0, 0, 0}, .par.move.src = {1, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_wz_zx                          , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 2, .par.move.dst = {3, 2, 0, 0, 0, 0}, .par.move.src = {2, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_xyz_yzw                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {0, 1, 2, 0, 0, 0}, .par.move.src = {1, 2, 3, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_xzy_zyw                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {0, 2, 1, 0, 0, 0}, .par.move.src = {2, 1, 3, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_yzw_xxx                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {1, 2, 3, 0, 0, 0}, .par.move.src = {0, 0, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_zwy_xyx                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {2, 3, 1, 0, 0, 0}, .par.move.src = {0, 1, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_wyz_yzx                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {3, 1, 2, 0, 0, 0}, .par.move.src = {1, 2, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_wzy_zyx                        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 3, .par.move.dst = {3, 2, 1, 0, 0, 0}, .par.move.src = {2, 1, 0, 0, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_xtyz_wyzt                      , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {0, -1, 1, 2, 0, 0}, .par.move.src = {3, 1, 2, -1, 0, 0}) \
+    MACRO(__VA_ARGS__, u32_copy_wtyz_xyzt                      , .type = SWS_PIXEL_U32, .uop = SWS_UOP_COPY            , .mask = 0x0, .par.move.num_moves = 4, .par.move.dst = {3, -1, 1, 2, 0, 0}, .par.move.src = {0, 1, 2, -1, 0, 0})
 #define SWS_FOR_U32_SWAP_BYTES(MACRO, ...) \
     MACRO(__VA_ARGS__, u32_swap_bytes_x                        , SWS_PIXEL_U32, SWS_UOP_SWAP_BYTES      , 0x1) \
     MACRO(__VA_ARGS__, u32_swap_bytes_xy                       , SWS_PIXEL_U32, SWS_UOP_SWAP_BYTES      , 0x3) \
@@ -961,8 +845,6 @@
 #define SWS_FOR_STRUCT_F32_PERMUTE(MACRO, ...)
 #define SWS_FOR_F32_COPY(MACRO, ...)
 #define SWS_FOR_STRUCT_F32_COPY(MACRO, ...)
-#define SWS_FOR_F32_MOVE(MACRO, ...)
-#define SWS_FOR_STRUCT_F32_MOVE(MACRO, ...)
 #define SWS_FOR_F32_SWAP_BYTES(MACRO, ...)
 #define SWS_FOR_STRUCT_F32_SWAP_BYTES(MACRO, ...)
 #define SWS_FOR_F32_EXPAND_BIT(MACRO, ...)
diff --git a/libswscale/uops_macros_gen.c b/libswscale/uops_macros_gen.c
index 4181b3abde..33e328fcc3 100644
--- a/libswscale/uops_macros_gen.c
+++ b/libswscale/uops_macros_gen.c
@@ -79,11 +79,6 @@ static int generate_entry_struct(void *opaque, void *key)
         break;
     case SWS_UOP_PERMUTE:
     case SWS_UOP_COPY:
-        av_bprintf(bp, ", .par.swizzle.in = {%d, %d, %d, %d}",
-                   par->swizzle.in[0], par->swizzle.in[1],
-                   par->swizzle.in[2], par->swizzle.in[3]);
-        break;
-    case SWS_UOP_MOVE:
         av_bprintf(bp, ", .par.move.num_moves = %d", par->move.num_moves);
         av_bprintf(bp, ", .par.move.dst = {%d, %d, %d, %d, %d, %d}",
                    par->move.dst[0], par->move.dst[1], par->move.dst[2],
@@ -144,11 +139,6 @@ static int generate_entry_args(void *opaque, void *key)
         break;
     case SWS_UOP_PERMUTE:
     case SWS_UOP_COPY:
-        av_bprintf(bp, ", %d, %d, %d, %d",
-                   par->swizzle.in[0], par->swizzle.in[1],
-                   par->swizzle.in[2], par->swizzle.in[3]);
-        break;
-    case SWS_UOP_MOVE:
         av_bprintf(bp, ", %d", par->move.num_moves);
         av_bprintf(bp, ", %d, %d, %d, %d, %d, %d",
                    par->move.dst[0], par->move.dst[1], par->move.dst[2],
@@ -229,7 +219,7 @@ fail:
 
 static const SwsUOpFlags uop_flags[] = {
     0,
-    SWS_UOP_FLAG_FMA | SWS_UOP_FLAG_MOVE, /* x86 backend */
+    SWS_UOP_FLAG_FMA, /* x86 backend */
 };
 
 static int register_uops(SwsContext *ctx, const SwsOpList *ops,
diff --git a/libswscale/uops_tmpl.c b/libswscale/uops_tmpl.c
index 214f7a0ef9..001ae02c7e 100644
--- a/libswscale/uops_tmpl.c
+++ b/libswscale/uops_tmpl.c
@@ -360,35 +360,47 @@ SWS_FOR_STRUCT(PX, READ_PLANAR_FH, DECL_ENTRY, .setup = fn(setup_filter_h) )
  * Permutation and copying *
  ***************************/
 
-/* Permute by directly swapping the order of arguments to the continuation. */
-#define DECL_PERMUTE(DUMMY, NAME, TYPE, UOP, MASK, IDX0, IDX1, IDX2, IDX3)      \
-    static void NAME##_c(SwsOpIter *restrict iter,                              \
-                         const SwsOpImpl *restrict impl,                        \
-                         void *restrict in0, void *restrict in1,                \
-                         void *restrict in2, void *restrict in3)                \
-    {                                                                           \
-        CONTINUE(in##IDX0, in##IDX1, in##IDX2, in##IDX3);                       \
-    }
+DECL_FUNC(permute, const SwsCompMask mask, int num_moves,
+          int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5,
+          int8_t s0, int8_t s1, int8_t s2, int8_t s3, int8_t s4, int8_t s5)
+{
+    const int8_t dst[SWS_UOP_MOVE_MAX] = { d0, d1, d2, d3, d4, d5 };
+    const int8_t src[SWS_UOP_MOVE_MAX] = { s0, s1, s2, s3, s4, s5 };
 
-#define DECL_COPY(DUMMY, NAME, TYPE, UOP, MASK, IDX0, IDX1, IDX2, IDX3)         \
-    static void NAME##_c(SwsOpIter *restrict iter,                              \
-                         const SwsOpImpl *restrict impl,                        \
-                         void *restrict in0, void *restrict in1,                \
-                         void *restrict in2, void *restrict in3)                \
-    {                                                                           \
-        const SwsCompMask mask = (MASK);                                        \
-        block_t x, y, z, w;                                                     \
-                                                                                \
-        if (X) memcpy(&x.px, in##IDX0, SIZEOF_BLOCK);                           \
-        if (Y) memcpy(&y.px, in##IDX1, SIZEOF_BLOCK);                           \
-        if (Z) memcpy(&z.px, in##IDX2, SIZEOF_BLOCK);                           \
-        if (W) memcpy(&w.px, in##IDX3, SIZEOF_BLOCK);                           \
-                                                                                \
-        CONTINUE(X ? &x : in0, Y ? &y : in1, Z ? &z : in2, W ? &w : in3);       \
-    }
+    pixel_t *ptr[5] = { NULL, x, y, z, w };
+    for (int n = 0; n < num_moves; n++)
+        ptr[dst[n] + 1] = ptr[src[n] + 1];
 
-SWS_FOR(PX, PERMUTE, DECL_PERMUTE)
-SWS_FOR(PX, COPY,    DECL_COPY)
+    CONTINUE(ptr[1], ptr[2], ptr[3], ptr[4]);
+}
+
+DECL_FUNC(copy, const SwsCompMask mask, int num_moves,
+          int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5,
+          int8_t s0, int8_t s1, int8_t s2, int8_t s3, int8_t s4, int8_t s5)
+{
+    const size_t block_size = SWS_BLOCK_SIZE * sizeof(pixel_t);
+    const int8_t dst[SWS_UOP_MOVE_MAX] = { d0, d1, d2, d3, d4, d5 };
+    const int8_t src[SWS_UOP_MOVE_MAX] = { s0, s1, s2, s3, s4, s5 };
+
+    block_t data[5];
+    memcpy(&data[1].px, x, block_size);
+    memcpy(&data[2].px, y, block_size);
+    memcpy(&data[3].px, z, block_size);
+    memcpy(&data[4].px, w, block_size);
+
+    for (int n = 0; n < num_moves; n++)
+        data[dst[n] + 1] = data[src[n] + 1];
+
+    memcpy(x, &data[1].px, block_size);
+    memcpy(y, &data[2].px, block_size);
+    memcpy(z, &data[3].px, block_size);
+    memcpy(w, &data[4].px, block_size);
+
+    CONTINUE(x, y, z, w);
+}
+
+SWS_FOR(PX, PERMUTE, DECL_IMPL, permute)
+SWS_FOR(PX, COPY,    DECL_IMPL, copy)
 SWS_FOR_STRUCT(PX, PERMUTE, DECL_ENTRY)
 SWS_FOR_STRUCT(PX, COPY,    DECL_ENTRY)
 
diff --git a/libswscale/x86/ops.c b/libswscale/x86/ops.c
index 8312bf6d07..4ad22cfddd 100644
--- a/libswscale/x86/ops.c
+++ b/libswscale/x86/ops.c
@@ -318,7 +318,8 @@ SWS_FOR_STRUCT(TYPE, WRITE_NIBBLE,    DECL_ENTRY, EXT, NULL, NULL)
 SWS_FOR_STRUCT(TYPE, WRITE_BIT,       DECL_ENTRY, EXT, NULL, NULL)              \
 SWS_FOR_STRUCT(TYPE, SWAP_BYTES,      DECL_ENTRY, EXT, NULL, NULL)              \
 SWS_FOR_STRUCT(TYPE, EXPAND_BIT,      DECL_ENTRY, EXT, NULL, NULL)              \
-SWS_FOR_STRUCT(TYPE, MOVE,            DECL_ENTRY, EXT, NULL, NULL)              \
+SWS_FOR_STRUCT(TYPE, PERMUTE,         DECL_ENTRY, EXT, NULL, NULL)              \
+SWS_FOR_STRUCT(TYPE, COPY,            DECL_ENTRY, EXT, NULL, NULL)              \
 SWS_FOR_STRUCT(TYPE, SCALE,           DECL_ENTRY, EXT, NULL, setup_scale)       \
 SWS_FOR_STRUCT(TYPE, ADD,             DECL_ENTRY, EXT, NULL, ff_sws_setup_vec4) \
 SWS_FOR_STRUCT(TYPE, MIN,             DECL_ENTRY, EXT, NULL, ff_sws_setup_vec4) \
@@ -341,7 +342,8 @@ SWS_FOR_STRUCT(TYPE, DITHER,          DECL_ENTRY, EXT, NULL, setup_dither)
     SWS_FOR(TYPE, WRITE_BIT,      REF_ENTRY, EXT)                               \
     SWS_FOR(TYPE, SWAP_BYTES,     REF_ENTRY, EXT)                               \
     SWS_FOR(TYPE, EXPAND_BIT,     REF_ENTRY, EXT)                               \
-    SWS_FOR(TYPE, MOVE,           REF_ENTRY, EXT)                               \
+    SWS_FOR(TYPE, PERMUTE,        REF_ENTRY, EXT)                               \
+    SWS_FOR(TYPE, COPY,           REF_ENTRY, EXT)                               \
     SWS_FOR(TYPE, SCALE,          REF_ENTRY, EXT)                               \
     SWS_FOR(TYPE, ADD,            REF_ENTRY, EXT)                               \
     SWS_FOR(TYPE, MIN,            REF_ENTRY, EXT)                               \
@@ -661,7 +663,7 @@ static int compile_x86(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out
     if (!EXTERNAL_SSE4(cpu_flags))
         return AVERROR(ENOTSUP);
 
-    SwsUOpFlags flags = SWS_UOP_FLAG_MOVE;
+    SwsUOpFlags flags = 0;
     if (EXTERNAL_FMA3(cpu_flags))
         flags |= SWS_UOP_FLAG_FMA;
 
diff --git a/libswscale/x86/ops_int.asm b/libswscale/x86/ops_int.asm
index 395feb9531..76e369d1fa 100644
--- a/libswscale/x86/ops_int.asm
+++ b/libswscale/x86/ops_int.asm
@@ -781,7 +781,8 @@ assert 0, SWS_UOP_DITHER is not implemented for integer types
     DECL_%1_WRITE_PACKED    (WRITE_PACKED)
     DECL_%1_WRITE_NIBBLE    (WRITE_NIBBLE)
     DECL_%1_WRITE_BIT       (WRITE_BIT)
-    DECL_%1_MOVE            (MOVE)
+    DECL_%1_PERMUTE         (MOVE)
+    DECL_%1_COPY            (MOVE)
     DECL_%1_SWAP_BYTES      (SWAP_BYTES)
     DECL_%1_EXPAND_BIT      (EXPAND_BIT)
     DECL_%1_SCALE           (SCALE)
diff --git a/libswscale/x86/uops_macros.asm.h b/libswscale/x86/uops_macros.asm.h
index fce08f320f..971f68c880 100644
--- a/libswscale/x86/uops_macros.asm.h
+++ b/libswscale/x86/uops_macros.asm.h
@@ -62,7 +62,8 @@
     {DEF_MACRO(WRITE_NIBBLE,        TYPE)}, \
     {DEF_MACRO(WRITE_PACKED,        TYPE)}, \
     {DEF_MACRO(WRITE_PLANAR,        TYPE)}, \
-    {DEF_MACRO(MOVE,                TYPE)}, \
+    {DEF_MACRO(PERMUTE,             TYPE)}, \
+    {DEF_MACRO(COPY,                TYPE)}, \
     {DEF_MACRO(SWAP_BYTES,          TYPE)}, \
     {DEF_MACRO(EXPAND_BIT,          TYPE)}, \
     {DEF_MACRO(EXPAND_PAIR,         TYPE)}, \
diff --git a/tests/checkasm/sw_ops.c b/tests/checkasm/sw_ops.c
index bf83d753d4..22c46e4add 100644
--- a/tests/checkasm/sw_ops.c
+++ b/tests/checkasm/sw_ops.c
@@ -577,11 +577,15 @@ static void check_expand(const char *name, const SwsUOp *uop)
 
 static void check_swizzle(const char *name, const SwsUOp *uop)
 {
-    const SwsSwizzleUOp *swiz = &uop->par.swizzle;
-    CHECK_MASK(name, uop->mask, NULL, uop->type, uop->type, {
+    const SwsMoveUOp *move = &uop->par.move;
+    int8_t idx[4 + 1] = { -1, 0, 1, 2, 3 };
+    for (int n = 0; n < move->num_moves; n++)
+        idx[move->dst[n] + 1] = idx[move->src[n] + 1];
+
+    CHECK(name, 4, 4, uop->type, uop->type, {
         .op   = SWS_OP_SWIZZLE,
         .type = uop->type,
-        .swizzle.in = { swiz->in[0], swiz->in[1], swiz->in[2], swiz->in[3] },
+        .swizzle.in = { idx[1], idx[2], idx[3], idx[4] },
     });
 }
 
diff --git a/tests/ref/fate/sws-ops-list b/tests/ref/fate/sws-ops-list
index 6d60f02ec1..02679573af 100644
--- a/tests/ref/fate/sws-ops-list
+++ b/tests/ref/fate/sws-ops-list
@@ -1 +1 @@
-53c637960d4d49e638a9ed8766266875
+040fb423b6e2268952cfd1ae8a5f7f79
-- 
2.52.0


>From 53972c105cc6b2071f2183c1adf682baf898b7fe Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Wed, 8 Jul 2026 02:05:46 +0200
Subject: [PATCH 09/10] swscale/x86/ops: add missing non-FMA SWS_UOP_LINEAR
 fallback

Needed for platforms without SSE4.1 support, as well as checkasm.

Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/x86/ops.c             | 2 ++
 libswscale/x86/ops_float.asm     | 5 +++++
 libswscale/x86/uops_macros.asm.h | 1 +
 3 files changed, 8 insertions(+)

diff --git a/libswscale/x86/ops.c b/libswscale/x86/ops.c
index 4ad22cfddd..b4a5b5d082 100644
--- a/libswscale/x86/ops.c
+++ b/libswscale/x86/ops.c
@@ -328,6 +328,7 @@ SWS_FOR_STRUCT(TYPE, UNPACK,          DECL_ENTRY, EXT, NULL, NULL)
 SWS_FOR_STRUCT(TYPE, PACK,            DECL_ENTRY, EXT, NULL, NULL)              \
 SWS_FOR_STRUCT(TYPE, LSHIFT,          DECL_ENTRY, EXT, NULL, NULL)              \
 SWS_FOR_STRUCT(TYPE, RSHIFT,          DECL_ENTRY, EXT, NULL, NULL)              \
+SWS_FOR_STRUCT(TYPE, LINEAR,          DECL_ENTRY, EXT, NULL, setup_linear)      \
 SWS_FOR_STRUCT(TYPE, LINEAR_FMA,      DECL_ENTRY, EXT, NULL, setup_linear)      \
 SWS_FOR_STRUCT(TYPE, DITHER,          DECL_ENTRY, EXT, NULL, setup_dither)      \
 /* end of macro */
@@ -352,6 +353,7 @@ SWS_FOR_STRUCT(TYPE, DITHER,          DECL_ENTRY, EXT, NULL, setup_dither)
     SWS_FOR(TYPE, PACK,           REF_ENTRY, EXT)                               \
     SWS_FOR(TYPE, LSHIFT,         REF_ENTRY, EXT)                               \
     SWS_FOR(TYPE, RSHIFT,         REF_ENTRY, EXT)                               \
+    SWS_FOR(TYPE, LINEAR,         REF_ENTRY, EXT)                               \
     SWS_FOR(TYPE, LINEAR_FMA,     REF_ENTRY, EXT)                               \
     SWS_FOR(TYPE, DITHER,         REF_ENTRY, EXT)                               \
     /* end of macro */
diff --git a/libswscale/x86/ops_float.asm b/libswscale/x86/ops_float.asm
index 13f110b20b..3b8055c31a 100644
--- a/libswscale/x86/ops_float.asm
+++ b/libswscale/x86/ops_float.asm
@@ -603,6 +603,10 @@ IF W,   mova mw2, m11
         CONTINUE tmp1q
 %endmacro
 
+%macro LINEAR 2
+        LINEAR_FMA %1, %2, 0
+%endmacro
+
 ;---------------------------------------------------------
 ; Dithering
 
@@ -687,6 +691,7 @@ IF W,   addps mw2, m11
     DECL_%1_ADD             (ADD)
     DECL_%1_MIN             (MIN)
     DECL_%1_MAX             (MAX)
+    DECL_%1_LINEAR          (LINEAR)
     DECL_%1_LINEAR_FMA      (LINEAR_FMA)
     DECL_%1_DITHER          (DITHER)
 %endmacro
diff --git a/libswscale/x86/uops_macros.asm.h b/libswscale/x86/uops_macros.asm.h
index 971f68c880..f855817760 100644
--- a/libswscale/x86/uops_macros.asm.h
+++ b/libswscale/x86/uops_macros.asm.h
@@ -73,6 +73,7 @@
     {DEF_MACRO(TO_U32,              TYPE)}, \
     {DEF_MACRO(TO_F32,              TYPE)}, \
     {DEF_MACRO(SCALE,               TYPE)}, \
+    {DEF_MACRO(LINEAR,              TYPE)}, \
     {DEF_MACRO(LINEAR_FMA,          TYPE)}, \
     {DEF_MACRO(ADD,                 TYPE)}, \
     {DEF_MACRO(MIN,                 TYPE)}, \
-- 
2.52.0


>From 437ba651b8caef70f0a1c1f15c71569315c1a288 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Wed, 8 Jul 2026 01:43:56 +0200
Subject: [PATCH 10/10] swscale/tests/sws_ops: rewrite to test uops directly

Instead of awkwardly reverse-engineering each uop to reflect
it back to the corresponding SwsOp, this leverages the new
compile_uops() API to directly test the uop in question.

This is not only vastly simpler but also fixes several major
shortcomings with the previous design, such as always having
to keep the reflection code in sync for any newly added uop,
or not testing uops that get translated to a packed shuffle
fast path.

The major downside is that arch-specific uops can now no longer
be tested against the C reference unless we specifically add
a C reference function for each relevant uop; and also, that the
packed shuffle fast path is currently no longer tested by checkasm.
(But this will be fixed by my upcoming pshufb uop series)

$ time checkasm --test=sw_ops --repeat=10 # 1.85s -> 1.39s

Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/uops.h       |   1 +
 tests/checkasm/sw_ops.c | 722 ++++++++++++++++------------------------
 2 files changed, 287 insertions(+), 436 deletions(-)

diff --git a/libswscale/uops.h b/libswscale/uops.h
index 3c83941e10..d90c03efcd 100644
--- a/libswscale/uops.h
+++ b/libswscale/uops.h
@@ -71,6 +71,7 @@ enum {
 #define SWS_COMP_TEST(mask, X) (!!((mask) & SWS_COMP(X)))
 #define SWS_COMP_INV(mask) ((mask) ^ SWS_COMP_ALL)
 #define SWS_COMP_ELEMS(N) ((1 << (N)) - 1)
+#define SWS_COMP_COUNT(mask) (av_popcount((mask) & SWS_COMP_ALL))
 #define SWS_COMP_MASK(X, Y, Z, W)   \
     (((X) ? SWS_COMP(0) : 0) |      \
      ((Y) ? SWS_COMP(1) : 0) |      \
diff --git a/tests/checkasm/sw_ops.c b/tests/checkasm/sw_ops.c
index 22c46e4add..8caee1325b 100644
--- a/tests/checkasm/sw_ops.c
+++ b/tests/checkasm/sw_ops.c
@@ -24,7 +24,7 @@
 #include "libavutil/mem_internal.h"
 #include "libavutil/refstruct.h"
 
-#include "libswscale/ops.h"
+#include "libswscale/filters.h"
 #include "libswscale/ops_dispatch.h"
 #include "libswscale/uops.h"
 #include "libswscale/uops_macros.h"
@@ -32,17 +32,26 @@
 #include "checkasm.h"
 
 enum {
+    MAX_UOPS    = 3, /* read, op, write */
     NB_PLANES   = 4,
     PIXELS      = 64,
     LINES       = 16,
 };
 
-enum {
-    U8  = SWS_PIXEL_U8,
-    U16 = SWS_PIXEL_U16,
-    U32 = SWS_PIXEL_U32,
-    F32 = SWS_PIXEL_F32,
-};
+typedef struct Test {
+    const char  *name;
+    SwsUOp       uops[MAX_UOPS];
+    int          num_uops;
+
+    /* Extra metadata for the test harness */
+    SwsPixelType type_in;           /* data format to fill */
+    SwsPixelType type_out;          /* data format to compare */
+    SwsCompMask  planes_in;         /* planes to fill */
+    SwsCompMask  planes_out;        /* planes to compare */
+    int          pixel_bits_in;     /* read pixel stride */
+    int          pixel_bits_out;    /* write pixel stride */
+    unsigned     ranges[NB_PLANES]; /* pixel range to fill */
+} Test;
 
 #define FMT(fmt, ...) tprintf((char[256]) {0}, 256, fmt, __VA_ARGS__)
 static const char *tprintf(char buf[], size_t size, const char *fmt, ...)
@@ -54,23 +63,6 @@ static const char *tprintf(char buf[], size_t size, const char *fmt, ...)
     return buf;
 }
 
-static int rw_pixel_bits(const SwsOp *op)
-{
-    if (op->rw.mode == SWS_RW_PALETTE)
-        return 8; /* index size */
-
-    int elems = 0;
-    switch (op->rw.mode) {
-    case SWS_RW_PLANAR: elems = 1; break;
-    case SWS_RW_PACKED: elems = op->rw.elems; break;
-    }
-
-    const int size  = ff_sws_pixel_type_size(op->type);
-    const int bits  = 8 >> op->rw.frac;
-    av_assert1(bits >= 1);
-    return elems * size * bits;
-}
-
 static float rndf(void)
 {
     union { uint32_t u; float f; } x;
@@ -80,6 +72,17 @@ static float rndf(void)
     return x.f;
 }
 
+static SwsPixel rndpx(SwsPixelType type)
+{
+    switch (type) {
+    case SWS_PIXEL_U8:  return (SwsPixel) { .u8  = rnd() & 0xFF };
+    case SWS_PIXEL_U16: return (SwsPixel) { .u16 = rnd() & 0xFFFF };
+    case SWS_PIXEL_U32: return (SwsPixel) { .u32 = rnd()  };
+    case SWS_PIXEL_F32: return (SwsPixel) { .f32 = rndf() };
+    default: return (SwsPixel) {0};
+    }
+}
+
 static void fill32f(float *line, int num, unsigned range)
 {
     const float scale = (float) range / UINT32_MAX;
@@ -113,17 +116,20 @@ static void fill8(uint8_t *line, int num, unsigned range)
     }
 }
 
-static void set_range(AVRational64 *rangeq, unsigned range, unsigned range_def)
+static SwsPixelType pixel_type_to_int(const SwsPixelType type)
 {
-    if (!range)
-        range = range_def;
-    if (range)
-        *rangeq = (AVRational64) { range, 1 };
+    switch (ff_sws_pixel_type_size(type)) {
+    case 1: return SWS_PIXEL_U8;
+    case 2: return SWS_PIXEL_U16;
+    case 4: return SWS_PIXEL_U32;
+    default: break;
+    }
+
+    av_unreachable("Invalid pixel type!");
+    return SWS_PIXEL_NONE;
 }
 
-static void check_compiled(const char *name,
-                           const SwsOp *read_op, const SwsOp *write_op,
-                           const int ranges[NB_PLANES],
+static void check_compiled(const Test *test,
                            const SwsCompiledOp *comp_ref,
                            const SwsCompiledOp *comp_new)
 {
@@ -134,7 +140,7 @@ static void check_compiled(const char *name,
      */
     uintptr_t id = (uintptr_t) comp_new->func;
     id ^= (id << 6) + (id >> 2) + 0x9e3779b97f4a7c15 + comp_new->cpu_flags;
-    if (!check_key(id, "%s", name))
+    if (!check_key(id, "%s", test->name))
         return;
 
     declare_func(void, const SwsOpExec *, const void *, int bx, int y, int bx_end, int y_end);
@@ -147,18 +153,23 @@ static void check_compiled(const char *name,
     av_assert0(PIXELS % comp_new->block_size == 0);
     for (int p = 0; p < NB_PLANES; p++) {
         void *plane = src0[p];
-        switch (read_op->type) {
-        case U8:
-            fill8(plane, sizeof(src0[p]) /  sizeof(uint8_t), ranges[p]);
+        if (!SWS_COMP_TEST(test->planes_in, p)) {
+            memset(plane, 0, sizeof(src0[p]));
+            continue;
+        }
+
+        switch (test->type_in) {
+        case SWS_PIXEL_U8:
+            fill8(plane, sizeof(src0[p]) / sizeof(uint8_t), test->ranges[p]);
             break;
-        case U16:
-            fill16(plane, sizeof(src0[p]) / sizeof(uint16_t), ranges[p]);
+        case SWS_PIXEL_U16:
+            fill16(plane, sizeof(src0[p]) / sizeof(uint16_t), test->ranges[p]);
             break;
-        case U32:
-            fill32(plane, sizeof(src0[p]) / sizeof(uint32_t), ranges[p]);
+        case SWS_PIXEL_U32:
+            fill32(plane, sizeof(src0[p]) / sizeof(uint32_t), test->ranges[p]);
             break;
-        case F32:
-            fill32f(plane, sizeof(src0[p]) / sizeof(uint32_t), ranges[p]);
+        case SWS_PIXEL_F32:
+            fill32f(plane, sizeof(src0[p]) / sizeof(uint32_t), test->ranges[p]);
             break;
         }
     }
@@ -167,8 +178,8 @@ static void check_compiled(const char *name,
     memset(dst0, 0, sizeof(dst0));
     memset(dst1, 0, sizeof(dst1));
 
-    const int read_size  = PIXELS * rw_pixel_bits(read_op)  >> 3;
-    const int write_size = PIXELS * rw_pixel_bits(write_op) >> 3;
+    const int read_size  = PIXELS * test->pixel_bits_in  >> 3;
+    const int write_size = PIXELS * test->pixel_bits_out >> 3;
 
     SwsOpExec exec = {0};
     exec.width = PIXELS;
@@ -180,123 +191,100 @@ static void check_compiled(const char *name,
         exec.out_bump[i] = exec.out_stride[i] - write_size;
     }
 
-    if (read_op->rw.mode == SWS_RW_PALETTE) {
+    int32_t in_bump_y[LINES];
+    int32_t in_offset_x[PIXELS];
+    const SwsUOp *read_op = &test->uops[0];
+    switch (read_op->uop) {
+    case SWS_UOP_READ_PALETTE:
         static_assert(sizeof(src0[1]) >= sizeof(uint32_t[256]), "palette plane too small");
         exec.in_bump[1] = exec.in_stride[1] = 0;
-    }
-
-    int32_t in_bump_y[LINES];
-    if (read_op->rw.filter.op == SWS_OP_FILTER_V) {
-        const int *offsets = read_op->rw.filter.kernel->offsets;
+        break;
+    case SWS_UOP_READ_PLANAR_FV: {
+        const int *offsets = read_op->data.kernel->offsets;
         for (int y = 0; y < LINES - 1; y++)
             in_bump_y[y] = offsets[y + 1] - offsets[y] - 1;
         in_bump_y[LINES - 1] = 0;
         exec.in_bump_y = in_bump_y;
+        break;
     }
-
-    int32_t in_offset_x[PIXELS];
-    if (read_op->rw.filter.op == SWS_OP_FILTER_H) {
-        const int *offsets = read_op->rw.filter.kernel->offsets;
-        const int rw_bits = rw_pixel_bits(read_op);
+    case SWS_UOP_READ_PLANAR_FH: {
+        const int *offsets = read_op->data.kernel->offsets;
         for (int x = 0; x < PIXELS; x++)
-            in_offset_x[x] = offsets[x] * rw_bits >> 3;
+            in_offset_x[x] = offsets[x] * test->pixel_bits_in >> 3;
         exec.in_offset_x = in_offset_x;
     }
+    }
 
     for (int i = 0; i < NB_PLANES; i++) {
         exec.in[i]  = (void *) src0[i];
         exec.out[i] = (void *) dst0[i];
-        exec.block_size_in[i]  = comp_ref->block_size * rw_pixel_bits(read_op)  >> 3;
-        exec.block_size_out[i] = comp_ref->block_size * rw_pixel_bits(write_op) >> 3;
+        exec.block_size_in[i]  = comp_ref->block_size * test->pixel_bits_in  >> 3;
+        exec.block_size_out[i] = comp_ref->block_size * test->pixel_bits_out >> 3;
     }
     checkasm_call(comp_ref->func, &exec, comp_ref->priv, 0, 0, PIXELS / comp_ref->block_size, LINES);
 
     for (int i = 0; i < NB_PLANES; i++) {
         exec.in[i]  = (void *) src1[i];
         exec.out[i] = (void *) dst1[i];
-        exec.block_size_in[i]  = comp_new->block_size * rw_pixel_bits(read_op)  >> 3;
-        exec.block_size_out[i] = comp_new->block_size * rw_pixel_bits(write_op) >> 3;
+        exec.block_size_in[i]  = comp_new->block_size * test->pixel_bits_in  >> 3;
+        exec.block_size_out[i] = comp_new->block_size * test->pixel_bits_out >> 3;
     }
     checkasm_call_checked(comp_new->func, &exec, comp_new->priv, 0, 0, PIXELS / comp_new->block_size, LINES);
 
     for (int i = 0; i < NB_PLANES; i++) {
-        const char *desc = FMT("%s[%d]", name, i);
-        const int stride = sizeof(dst0[i][0]);
+        if (!SWS_COMP_TEST(test->planes_out, i))
+            continue;
 
-        switch (write_op->type) {
-        case U8:
+        const char *desc = FMT("%s[%d]", test->name, i);
+        const int stride = sizeof(dst0[i][0]);
+        switch (test->type_out) {
+        case SWS_PIXEL_U8:
             checkasm_check(uint8_t, (void *) dst0[i], stride,
                                     (void *) dst1[i], stride,
                                     write_size, LINES, desc);
             break;
-        case U16:
+        case SWS_PIXEL_U16:
             checkasm_check(uint16_t, (void *) dst0[i], stride,
                                      (void *) dst1[i], stride,
                                      write_size >> 1, LINES, desc);
             break;
-        case U32:
+        case SWS_PIXEL_U32:
             checkasm_check(uint32_t, (void *) dst0[i], stride,
                                      (void *) dst1[i], stride,
                                      write_size >> 2, LINES, desc);
             break;
-        case F32:
+        case SWS_PIXEL_F32:
             checkasm_check(float_ulp, (void *) dst0[i], stride,
                                       (void *) dst1[i], stride,
                                       write_size >> 2, LINES, desc, 0);
             break;
         }
-
-        if (write_op->rw.mode == SWS_RW_PACKED)
-            break;
     }
 
     bench(comp_new->func, &exec, comp_new->priv, 0, 0, PIXELS / comp_new->block_size, LINES);
 }
 
-static void check_ops(const char *name, const unsigned ranges[NB_PLANES],
-                      const SwsOp *ops)
+static void run_test(const Test *test)
 {
     SwsContext *ctx = sws_alloc_context();
     if (!ctx)
         return;
     ctx->flags = SWS_BITEXACT;
 
-    static const unsigned def_ranges[4] = {0};
-    if (!ranges)
-        ranges = def_ranges;
+    /* Generate dummy uop list on-stack */
+    SwsUOpList oplist = {
+        .ops        = (SwsUOp *) test->uops,
+        .num_ops    = test->num_uops,
 
-    const SwsOp *read_op, *write_op;
-    SwsOpList oplist = {
-        .ops = (SwsOp *) ops,
-        .plane_src = {0, 1, 2, 3},
-        .plane_dst = {0, 1, 2, 3},
+        /* Less efficient, but works universally */
+        .planes_in  = SWS_COMP_ALL,
+        .planes_out = SWS_COMP_ALL,
     };
 
-    read_op = &ops[0];
-    for (oplist.num_ops = 0; ops[oplist.num_ops].op; oplist.num_ops++)
-        write_op = &ops[oplist.num_ops];
-
-    for (int p = 0; p < NB_PLANES; p++) {
-        switch (read_op->type) {
-        case U8:
-            set_range(&oplist.comps_src.max[p], ranges[p], UINT8_MAX);
-            oplist.comps_src.min[p] = (AVRational64) { 0, 1 };
-            break;
-        case U16:
-            set_range(&oplist.comps_src.max[p], ranges[p], UINT16_MAX);
-            oplist.comps_src.min[p] = (AVRational64) { 0, 1 };
-            break;
-        case U32:
-            set_range(&oplist.comps_src.max[p], ranges[p], UINT32_MAX);
-            oplist.comps_src.min[p] = (AVRational64) { 0, 1 };
-            break;
-        case F32:
-            if (ranges[p]) {
-                oplist.comps_src.max[p] = (AVRational64) { ranges[p], 1 };
-                oplist.comps_src.min[p] = (AVRational64) { 0, 1 };
-            }
-            break;
-        }
+    for (int i = 0; i < test->num_uops; i++) {
+        const int pixel_size = ff_sws_pixel_type_size(test->uops[i].type);
+        if (pixel_size > oplist.pixel_size_max)
+            oplist.pixel_size_max = pixel_size;
     }
 
     static const SwsOpBackend *backend_ref;
@@ -312,7 +300,7 @@ static void check_ops(const char *name, const unsigned ranges[NB_PLANES],
 
     /* Always compile `ops` using the C backend as a reference */
     SwsCompiledOp comp_ref = {0};
-    int ret = ff_sws_ops_compile(ctx, backend_ref, &oplist, &comp_ref);
+    int ret = backend_ref->compile_uops(ctx, &oplist, &comp_ref);
     if (ret < 0) {
         av_assert0(ret != AVERROR(ENOTSUP));
         fail();
@@ -320,16 +308,18 @@ static void check_ops(const char *name, const unsigned ranges[NB_PLANES],
     }
 
     /* Check with the C backend to establish a reference */
-    check_compiled(name, read_op, write_op, ranges, &comp_ref, &comp_ref);
+    check_compiled(test, &comp_ref, &comp_ref);
 
     /* Iterate over every other backend, and test it against the C reference */
     for (int n = 0; ff_sws_op_backends[n]; n++) {
         const SwsOpBackend *backend = ff_sws_op_backends[n];
         if (backend->hw_format != AV_PIX_FMT_NONE || backend == backend_ref)
             continue;
+        if (!backend->compile_uops)
+            continue;
 
         SwsCompiledOp comp_new = {0};
-        int ret = ff_sws_ops_compile(ctx, backend, &oplist, &comp_new);
+        int ret = backend->compile_uops(ctx, &oplist, &comp_new);
         if (ret == AVERROR(ENOTSUP)) {
             continue;
         } else if (ret < 0) {
@@ -339,7 +329,7 @@ static void check_ops(const char *name, const unsigned ranges[NB_PLANES],
 
         /* Distinguish backends from each other even with same CPU flags */
         checkasm_set_func_variant("%s_%s", backend->name, checkasm_get_cpu_suffix());
-        check_compiled(name, read_op, write_op, ranges, &comp_ref, &comp_new);
+        check_compiled(test, &comp_ref, &comp_new);
         ff_sws_compiled_op_unref(&comp_new);
     }
 
@@ -348,127 +338,159 @@ done:
     sws_free_context(&ctx);
 }
 
-#define CHECK_RANGES(NAME, RANGES, N_IN, N_OUT, IN, OUT, ...)                   \
-  do {                                                                          \
-      check_ops(NAME, RANGES, (SwsOp[]) {                                       \
-        {                                                                       \
-            .op = SWS_OP_READ,                                                  \
-            .type = IN,                                                         \
-            .rw.elems = N_IN,                                                   \
-        },                                                                      \
-        __VA_ARGS__,                                                            \
-        {                                                                       \
-            .op = SWS_OP_WRITE,                                                 \
-            .type = OUT,                                                        \
-            .rw.elems = N_OUT,                                                  \
-        }, {0}                                                                  \
-    });                                                                         \
-  } while (0)
+static void check_uop(const char *name, const SwsUOp *uop,
+                      SwsCompMask mask_in, SwsCompMask mask_out,
+                      const unsigned ranges[NB_PLANES])
+{
+    Test t = {
+        .name     = name,
+        .type_in  = uop->type,
+        .type_out = uop->type,
+    };
+
+    for (int i = 0; ranges && i < NB_PLANES; i++)
+        t.ranges[i] = ranges[i];
+
+    /* uops with non-standard output type conversions */
+    switch (uop->uop) {
+    case SWS_UOP_TO_U8:  t.type_out = SWS_PIXEL_U8;  break;
+    case SWS_UOP_TO_U16: t.type_out = SWS_PIXEL_U16; break;
+    case SWS_UOP_TO_U32: t.type_out = SWS_PIXEL_U32; break;
+    case SWS_UOP_TO_F32: t.type_out = SWS_PIXEL_F32; break;
+    case SWS_UOP_EXPAND_PAIR: t.type_out = SWS_PIXEL_U16; break;
+    case SWS_UOP_EXPAND_QUAD: t.type_out = SWS_PIXEL_U32; break;
+    case SWS_UOP_READ_PLANAR_FH:
+    case SWS_UOP_READ_PLANAR_FV:
+        t.type_out = uop->par.filter.type;
+        break;
+    }
+
+    /* Set up read/write metadata for rw uops */
+    const int bits_in  = ff_sws_pixel_type_size(t.type_in)  * 8;
+    const int bits_out = ff_sws_pixel_type_size(t.type_out) * 8;
+    switch (uop->uop) {
+    case SWS_UOP_READ_PLANAR:
+    case SWS_UOP_READ_PLANAR_FH:
+    case SWS_UOP_READ_PLANAR_FV:
+        t.planes_in = uop->mask;
+        t.pixel_bits_in = bits_in;
+        break;
+    case SWS_UOP_WRITE_PLANAR:
+        t.planes_out = uop->mask;
+        t.pixel_bits_out = bits_out;
+        break;
+    case SWS_UOP_READ_PACKED:
+        t.planes_in = SWS_COMP_ELEMS(1);
+        t.pixel_bits_in = bits_in * SWS_COMP_COUNT(uop->mask);
+        break;
+    case SWS_UOP_WRITE_PACKED:
+        t.planes_out = SWS_COMP_ELEMS(1);
+        t.pixel_bits_out = bits_out * SWS_COMP_COUNT(uop->mask);
+        break;
+    case SWS_UOP_READ_NIBBLE:
+        t.planes_in = SWS_COMP_ELEMS(1);
+        t.pixel_bits_in = 4;
+        break;
+    case SWS_UOP_WRITE_NIBBLE:
+        t.planes_out = SWS_COMP_ELEMS(1);
+        t.pixel_bits_out = 4;
+        break;
+    case SWS_UOP_READ_BIT:
+        t.planes_in = SWS_COMP_ELEMS(1);
+        t.pixel_bits_in = 1;
+        break;
+    case SWS_UOP_WRITE_BIT:
+        t.planes_out = SWS_COMP_ELEMS(1);
+        t.pixel_bits_out = 1;
+        break;
+    case SWS_UOP_READ_PALETTE:
+        t.planes_in = SWS_COMP_ELEMS(2);
+        t.pixel_bits_in = 8; /* size of index */
+        break;
+    }
+
+    /* Add read uop if needed */
+    if (!t.planes_in) {
+        t.planes_in = mask_in;
+        t.pixel_bits_in = bits_in;
+        t.uops[t.num_uops++] = (SwsUOp) {
+            .type = pixel_type_to_int(t.type_in),
+            .uop  = SWS_UOP_READ_PLANAR,
+            .mask = SWS_COMP_ALL, /* extra planes are zero'd */
+        };
+    }
+
+    /* Add the UOp itself */
+    t.uops[t.num_uops++] = *uop;
+
+    /* Add write uop if needed */
+    if (!t.planes_out) {
+        t.planes_out = mask_out;
+        t.pixel_bits_out = bits_out;
+        t.uops[t.num_uops++] = (SwsUOp) {
+            .type = pixel_type_to_int(t.type_out),
+            .uop  = SWS_UOP_WRITE_PLANAR,
+            .mask = SWS_COMP_ALL, /* extra planes are ignored */
+        };
+    }
+
+    run_test(&t);
+}
+
+static void check_range(const char *name, const SwsUOp *uop,
+                        const unsigned ranges[NB_PLANES])
+{
+    /* Test all planes to ensure data remains untouched */
+    return check_uop(name, uop, SWS_COMP_ALL, SWS_COMP_ALL, ranges);
+}
+
+static void check_simple(const char *name, const SwsUOp *uop)
+{
+    return check_range(name, uop, NULL);
+}
+
+static void check_scalar(const char *name, SwsUOp *uop)
+{
+    uop->data.scalar = rndpx(uop->type);
+    check_simple(name, uop);
+}
+
+static void check_vec4(const char *name, SwsUOp *uop)
+{
+    for (int i = 0; i < 4; i++)
+        uop->data.vec4[i] = rndpx(uop->type);
+
+    return check_simple(name, uop);
+}
+
+static void check_mat4(const char *name, SwsUOp *uop)
+{
+    for (int i = 0; i < 4; i++) {
+        for (int j = 0; j < 5; j++)
+            uop->data.mat4[i][j] = rndpx(uop->type);
+    }
+
+    return check_simple(name, uop);
+}
 
 #define MK_RANGES(R) ((const unsigned[]) { R, R, R, R })
-#define CHECK_RANGE(NAME, RANGE, N_IN, N_OUT, IN, OUT, ...)                     \
-    CHECK_RANGES(NAME, MK_RANGES(RANGE), N_IN, N_OUT, IN, OUT, __VA_ARGS__)
 
-#define CHECK(NAME, N_IN, N_OUT, IN, OUT, ...) \
-    CHECK_RANGE(NAME, 0, N_IN, N_OUT, IN, OUT, __VA_ARGS__)
-
-static inline int mask_num(const SwsCompMask mask)
+static void check_read(const char *name, SwsUOp *uop)
 {
-    switch (mask) {
-    case SWS_COMP_ELEMS(1): return 1;
-    case SWS_COMP_ELEMS(2): return 2;
-    case SWS_COMP_ELEMS(3): return 3;
-    case SWS_COMP_ELEMS(4): return 4;
-    default: return 0;
-    }
-}
-
-#define CHECK_MASK(NAME, MASK, RANGES, IN, OUT, ...)                            \
-do {                                                                            \
-    const SwsCompMask mask = (MASK);                                            \
-    const int num = mask_num(mask);                                             \
-    if (!num)                                                                   \
-        break; /* can't test these with current infrastructure */               \
-    CHECK_RANGES(NAME, RANGES, 4, num, IN, OUT, __VA_ARGS__);                   \
-} while (0)
-
-static AVRational64 rndq(SwsPixelType t)
-{
-    const unsigned num = rnd();
-    if (ff_sws_pixel_type_is_int(t)) {
-        const int bits = ff_sws_pixel_type_size(t) * 8;
-        const unsigned mask = UINT_MAX >> (32 - bits);
-        return (AVRational64) { num & mask, 1 };
-    } else {
-        const unsigned den = rnd();
-        return (AVRational64) { num, den ? den : 1 };
-    }
-}
-
-static void check_read(const char *name, const SwsUOp *uop)
-{
-    SwsReadWriteMode mode;
-    switch (uop->uop) {
-    case SWS_UOP_READ_PACKED:
-    case SWS_UOP_READ_BIT:
-    case SWS_UOP_READ_NIBBLE:  mode = SWS_RW_PACKED; break;
-    case SWS_UOP_READ_PLANAR:  mode = SWS_RW_PLANAR; break;
-    case SWS_UOP_READ_PALETTE: mode = SWS_RW_PALETTE; break;
-    default: return;
-    }
-
-    const int num = mask_num(uop->mask);
-    check_ops(name, NULL, (SwsOp[]) {
-        {
-            .op        = SWS_OP_READ,
-            .type      = uop->type,
-            .rw.elems  = num,
-            .rw.mode   = mode,
-            .rw.frac   = uop->uop == SWS_UOP_READ_BIT    ? 3 :
-                         uop->uop == SWS_UOP_READ_NIBBLE ? 1 : 0,
-        }, {
-            .op        = SWS_OP_WRITE,
-            .type      = uop->type,
-            .rw.elems  = num,
-        }, {0}
-    });
+    check_uop(name, uop, uop->mask, uop->mask, NULL);
 }
 
 static void check_write(const char *name, const SwsUOp *uop)
 {
-    SwsReadWriteMode mode;
-    switch (uop->uop) {
-    case SWS_UOP_WRITE_BIT:
-    case SWS_UOP_WRITE_NIBBLE:
-    case SWS_UOP_WRITE_PACKED: mode = SWS_RW_PACKED; break;
-    case SWS_UOP_WRITE_PLANAR: mode = SWS_RW_PLANAR; break;
-    default: return;
-    }
-
     const int frac = uop->uop == SWS_UOP_WRITE_BIT    ? 3 :
                      uop->uop == SWS_UOP_WRITE_NIBBLE ? 1 : 0;
-    const int num = mask_num(uop->mask);
     const int bits = 8 >> frac;
     const unsigned range = (1 << bits) - 1;
-
-    check_ops(name, MK_RANGES(range), (SwsOp[]) {
-        {
-            .op        = SWS_OP_READ,
-            .type      = uop->type,
-            .rw.elems  = num,
-        }, {
-            .op        = SWS_OP_WRITE,
-            .type      = uop->type,
-            .rw.elems  = num,
-            .rw.mode   = mode,
-            .rw.frac   = frac,
-        }, {0}
-    });
+    check_uop(name, uop, uop->mask, uop->mask, MK_RANGES(range));
 }
 
-static void check_filter(const char *name, const SwsUOp *uop)
+static void check_filter(const char *name, SwsUOp *uop)
 {
-    const int num = mask_num(uop->mask);
     const bool is_vert = uop->uop == SWS_UOP_READ_PLANAR_FV;
 
     SwsFilterParams par = {
@@ -485,36 +507,26 @@ static void check_filter(const char *name, const SwsUOp *uop)
         par.scaler = scalers[s];
 
         for (par.src_size = 1; par.src_size <= par.dst_size; par.src_size <<= 1) {
-            SwsFilterWeights *filter;
-            if (ff_sws_filter_generate(NULL, &par, &filter) < 0) {
+            if (ff_sws_filter_generate(NULL, &par, &uop->data.kernel) < 0) {
                 fail();
                 return;
             }
 
             char desc[256];
-            snprintf(desc, sizeof(desc), "%s_%s_%d", name, filter->name, par.src_size);
-            check_ops(desc, NULL, (SwsOp[]) {
-                {
-                    .op        = SWS_OP_READ,
-                    .type      = uop->type,
-                    .rw.elems  = num,
-                    .rw.filter = {
-                        .op     = is_vert ? SWS_OP_FILTER_V : SWS_OP_FILTER_H,
-                        .kernel = filter,
-                        .type   = SWS_PIXEL_F32,
-                    },
-                }, {
-                    .op        = SWS_OP_WRITE,
-                    .type      = SWS_PIXEL_F32,
-                    .rw.elems  = num,
-                }, {0}
-            });
+            snprintf(desc, sizeof(desc), "%s_%s_%d", name,
+                     uop->data.kernel->name, par.src_size);
 
-            av_refstruct_unref(&filter);
+            check_read(desc, uop);
+            av_refstruct_unref(&uop->data.kernel);
         }
     }
 }
 
+static void check_expand_bit(const char *name, const SwsUOp *uop)
+{
+    check_range(name, uop, MK_RANGES(1));
+}
+
 static void check_cast(const char *name, const SwsUOp *uop)
 {
     SwsPixelType dst;
@@ -523,6 +535,8 @@ static void check_cast(const char *name, const SwsUOp *uop)
     case SWS_UOP_TO_U16: dst = SWS_PIXEL_U16; break;
     case SWS_UOP_TO_U32: dst = SWS_PIXEL_U32; break;
     case SWS_UOP_TO_F32: dst = SWS_PIXEL_F32; break;
+    case SWS_UOP_EXPAND_PAIR: dst = SWS_PIXEL_U16; break;
+    case SWS_UOP_EXPAND_QUAD: dst = SWS_PIXEL_U32; break;
     default: return;
     }
 
@@ -532,115 +546,33 @@ static void check_cast(const char *name, const SwsUOp *uop)
     if (isize < osize || !ff_sws_pixel_type_is_int(dst))
         range = 0;
 
-    CHECK_MASK(name, uop->mask, MK_RANGES(range), uop->type, dst, {
-        .op   = SWS_OP_CONVERT,
-        .type = uop->type,
-        .convert.to = dst,
-    });
+    check_uop(name, uop, uop->mask, uop->mask, MK_RANGES(range));
 }
 
-static void check_expand_bit(const char *name, const SwsUOp *uop)
-{
-    AVRational64 factor = { .den = 1 };
-    switch (uop->type) {
-    case SWS_PIXEL_U8:  factor.num = UINT8_MAX;  break;
-    case SWS_PIXEL_U16: factor.num = UINT16_MAX; break;
-    case SWS_PIXEL_U32: factor.num = UINT32_MAX; break;
-    default: return;
-    }
-
-    CHECK_MASK(name, uop->mask, MK_RANGES(1), uop->type, uop->type, {
-        .op   = SWS_OP_SCALE,
-        .type = uop->type,
-        .scale.factor = factor,
-    });
-}
-
-static void check_expand(const char *name, const SwsUOp *uop)
-{
-    SwsPixelType dst = SWS_PIXEL_NONE;
-    switch (uop->uop) {
-    case SWS_UOP_EXPAND_PAIR: dst = SWS_PIXEL_U16; break;
-    case SWS_UOP_EXPAND_QUAD: dst = SWS_PIXEL_U32; break;
-    }
-
-    av_assert0(uop->type == SWS_PIXEL_U8);
-    CHECK_MASK(name, uop->mask, NULL, uop->type, dst, {
-        .op   = SWS_OP_CONVERT,
-        .type = uop->type,
-        .convert = {
-            .to = dst,
-            .expand = true,
-        },
-    });
-}
-
-static void check_swizzle(const char *name, const SwsUOp *uop)
-{
-    const SwsMoveUOp *move = &uop->par.move;
-    int8_t idx[4 + 1] = { -1, 0, 1, 2, 3 };
-    for (int n = 0; n < move->num_moves; n++)
-        idx[move->dst[n] + 1] = idx[move->src[n] + 1];
-
-    CHECK(name, 4, 4, uop->type, uop->type, {
-        .op   = SWS_OP_SWIZZLE,
-        .type = uop->type,
-        .swizzle.in = { idx[1], idx[2], idx[3], idx[4] },
-    });
-}
-
-static void check_scale(const char *name, const SwsUOp *uop)
+static void check_scale(const char *name, SwsUOp *uop)
 {
+    const int bits = ff_sws_pixel_type_size(uop->type) * 8;
+    const unsigned max = UINT32_MAX >> (32 - bits);
+    SwsPixel scale = uop->data.scalar = rndpx(uop->type);
     unsigned range = 0;
-    AVRational64 scale;
 
-    if (ff_sws_pixel_type_is_int(uop->type)) {
-        /* Ensure the result won't exceed the value range */
-        const int bits = ff_sws_pixel_type_size(uop->type) * 8;
-        const unsigned max = UINT32_MAX >> (32 - bits);
-        scale = (AVRational64) { rnd() & (max >> 1), 1 };
-        range = max / (scale.num ? scale.num : 1);
-    } else {
-        scale = rndq(uop->type);
+    /* Ensure the result won't exceed the value range */
+    switch (uop->type) {
+    case SWS_PIXEL_U8:  range = max / (scale.u8  ? scale.u8  : 1); break;
+    case SWS_PIXEL_U16: range = max / (scale.u16 ? scale.u16 : 1); break;
+    case SWS_PIXEL_U32: range = max / (scale.u32 ? scale.u32 : 1); break;
     }
 
-    CHECK_MASK(name, uop->mask, MK_RANGES(range), uop->type, uop->type, {
-        .op   = SWS_OP_SCALE,
-        .type = uop->type,
-        .scale.factor = scale,
-    });
-}
-
-static void check_clamp(const char *name, const SwsUOp *uop)
-{
-    const SwsPixelType t = uop->type;
-    CHECK_MASK(name, uop->mask, NULL, t, t, {
-        .op   = uop->uop == SWS_UOP_MIN ? SWS_OP_MIN : SWS_OP_MAX,
-        .type = t,
-        .clamp.limit = { rndq(t), rndq(t), rndq(t), rndq(t) },
-    });
-}
-
-static void check_swap_bytes(const char *name, const SwsUOp *uop)
-{
-    CHECK_MASK(name, uop->mask, NULL, uop->type, uop->type, {
-        .op   = SWS_OP_SWAP_BYTES,
-        .type = uop->type,
-    });
+    check_range(name, uop, MK_RANGES(range));
 }
 
 static void check_unpack(const char *name, const SwsUOp *uop)
 {
     const uint8_t *pat = uop->par.pack.pattern;
-    const int num = pat[3] ? 4 : 3;
     const int total = pat[0] + pat[1] + pat[2] + pat[3];
     const unsigned range = UINT32_MAX >> (32 - total);
 
-    CHECK_RANGE(name, range, 1, num, uop->type, uop->type, {
-        .op   = SWS_OP_UNPACK,
-        .type = uop->type,
-        .pack.pattern = { pat[0], pat[1], pat[2], pat[3] },
-    });
+    check_uop(name, uop, SWS_COMP(0), uop->mask, MK_RANGES(range));
 }
 
 static void check_pack(const char *name, const SwsUOp *uop)
@@ -651,112 +583,30 @@ static void check_pack(const char *name, const SwsUOp *uop)
         (1 << pat[2]) - 1, (1 << pat[3]) - 1,
     };
 
-    CHECK_RANGES(name, ranges, 4, 1, uop->type, uop->type, {
-        .op   = SWS_OP_PACK,
-        .type = uop->type,
-        .pack.pattern = { pat[0], pat[1], pat[2], pat[3] },
-    });
+    check_uop(name, uop, uop->mask, SWS_COMP(0), ranges);
 }
 
-static void check_shift(const char *name, const SwsUOp *uop)
+static void check_dither(const char *name, SwsUOp *uop)
 {
-    CHECK_MASK(name, uop->mask, NULL, uop->type, uop->type, {
-        .op   = uop->uop == SWS_UOP_LSHIFT ? SWS_OP_LSHIFT : SWS_OP_RSHIFT,
-        .type = uop->type,
-        .shift.amount = uop->par.shift.amount,
-    });
-}
+    av_assert0(!ff_sws_pixel_type_is_int(uop->type));
 
-static void check_clear(const char *name, const SwsUOp *uop)
-{
-    const SwsPixelType type = uop->type;
-    const int bits = ff_sws_pixel_type_size(type) * 8;
-    const unsigned range  = UINT32_MAX >> (32 - bits);
-    const AVRational64 one  = (AVRational64) { (int) range, 1};
-    const AVRational64 zero = (AVRational64) { 0, 1};
-    const AVRational64 val  = { (rand() & 0x7F) | 1, 1 };
-
-    SwsClearOp clear = { .mask = uop->mask };
-    for (int i = 0; i < 4; i++) {
-        if (SWS_COMP_TEST(uop->par.clear.one, i))
-            clear.value[i] = one;
-        else if (SWS_COMP_TEST(uop->par.clear.zero, i))
-            clear.value[i] = zero;
-        else
-            clear.value[i] = val;
-    }
-
-    CHECK(name, 4, 4, type, type, {
-        .op    = SWS_OP_CLEAR,
-        .type  = type,
-        .clear = clear,
-    });
-}
-
-static void check_linear(const char *name, const SwsUOp *uop)
-{
-    const SwsPixelType type = uop->type;
-    av_assert0(!ff_sws_pixel_type_is_int(type));
-
-    SwsLinearOp lin;
-    for (int i = 0; i < 4; i++) {
-        for (int j = 0; j < 5; j++) {
-            if (uop->par.lin.one & SWS_MASK(i, j))
-                lin.m[i][j] = (AVRational64) { 1, 1 };
-            else if (uop->par.lin.zero & SWS_MASK(i, j))
-                lin.m[i][j] = (AVRational64) { 0, 1 };
-            else
-                lin.m[i][j] = rndq(type);
-        }
-    }
-
-    lin.mask = ff_sws_linear_mask(&lin);
-    CHECK(name, 4, 4, type, type, {
-        .op   = SWS_OP_LINEAR,
-        .type = type,
-        .lin  = lin,
-    });
-}
-
-static void check_dither(const char *name, const SwsUOp *uop)
-{
-    const SwsPixelType type = uop->type;
-    av_assert0(!ff_sws_pixel_type_is_int(type));
-
-    SwsDitherOp dither = { .size_log2 = uop->par.dither.size_log2 };
-    const int size = 1 << dither.size_log2;
-    const uint8_t *y_offset = uop->par.dither.y_offset;
-    for (int i = 0; i < 4; i++)
-        dither.y_offset[i] = SWS_COMP_TEST(uop->mask, i) ? y_offset[i] : -1;
-
-    dither.matrix = av_refstruct_allocz(size * size * sizeof(*dither.matrix));
-    if (!dither.matrix) {
+    const int size   = 1 << uop->par.dither.size_log2;
+    const int height = ff_sws_dither_height(&uop->par.dither);
+    SwsPixel *matrix = av_refstruct_allocz(size * height * sizeof(*matrix));
+    if (!matrix) {
         fail();
         return;
     }
 
     for (int i = 0; i < size * size; i++)
-        dither.matrix[i] = rndq(type);
+        matrix[i] = rndpx(uop->type);
+    memcpy(matrix + size * size, matrix,
+           size * (height - size) * sizeof(*matrix));
 
-    CHECK(name, 4, 4, type, type, {
-        .op     = SWS_OP_DITHER,
-        .type   = type,
-        .dither = dither,
-    });
+    uop->data.ptr = matrix;
+    check_simple(name, uop);
 
-    av_refstruct_unref(&dither.matrix);
-}
-
-static void check_add(const char *name, const SwsUOp *uop)
-{
-    /* SwsOp has no concept of SWS_OP_ADD; this is only used for
-     * SWS_OP_DITHER with a 1x1 dither matrix; so translate the uop */
-    check_dither(name, &(SwsUOp) {
-        .uop  = SWS_UOP_DITHER,
-        .type = uop->type,
-        .mask = uop->mask,
-        .par.dither.size_log2 = 0,
-    });
+    av_refstruct_unref(&matrix);
 }
 
 #define CHECK_FUNCTION(CHECK, NAME, ...) \
@@ -782,25 +632,25 @@ void checkasm_check_sw_ops(void)
     CHECK_FOR(WRITE_PACKED,     check_write);
     CHECK_FOR(WRITE_NIBBLE,     check_write);
     CHECK_FOR(WRITE_BIT,        check_write);
-    CHECK_FOR(PERMUTE,          check_swizzle);
-    CHECK_FOR(COPY,             check_swizzle);
+    CHECK_FOR(PERMUTE,          check_simple);
+    CHECK_FOR(COPY,             check_simple);
+    CHECK_FOR(SWAP_BYTES,       check_simple);
     CHECK_FOR(EXPAND_BIT,       check_expand_bit);
-    CHECK_FOR(EXPAND_PAIR,      check_expand);
-    CHECK_FOR(EXPAND_QUAD,      check_expand);
-    CHECK_FOR(SWAP_BYTES,       check_swap_bytes);
+    CHECK_FOR(EXPAND_PAIR,      check_cast);
+    CHECK_FOR(EXPAND_QUAD,      check_cast);
     CHECK_FOR(TO_U8,            check_cast);
     CHECK_FOR(TO_U16,           check_cast);
     CHECK_FOR(TO_U32,           check_cast);
     CHECK_FOR(TO_F32,           check_cast);
     CHECK_FOR(SCALE,            check_scale);
-    CHECK_FOR(ADD,              check_add);
-    CHECK_FOR(MIN,              check_clamp);
-    CHECK_FOR(MAX,              check_clamp);
+    CHECK_FOR(ADD,              check_scalar);
+    CHECK_FOR(MIN,              check_vec4);
+    CHECK_FOR(MAX,              check_vec4);
     CHECK_FOR(UNPACK,           check_unpack);
     CHECK_FOR(PACK,             check_pack);
-    CHECK_FOR(LSHIFT,           check_shift);
-    CHECK_FOR(RSHIFT,           check_shift);
-    CHECK_FOR(CLEAR,            check_clear);
-    CHECK_FOR(LINEAR,           check_linear);
+    CHECK_FOR(LSHIFT,           check_simple);
+    CHECK_FOR(RSHIFT,           check_simple);
+    CHECK_FOR(CLEAR,            check_vec4);
+    CHECK_FOR(LINEAR,           check_mat4);
     CHECK_FOR(DITHER,           check_dither);
 }
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]