diff mbox series

[2/2] tcg/riscv: Use BEXTI for single-bit extractions

Message ID 20250102181601.1421059-3-richard.henderson@linaro.org
State New
Headers show
Series tcg/riscv: Use BEXTI for single-bit extractions | expand

Commit Message

Richard Henderson Jan. 2, 2025, 6:16 p.m. UTC
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/riscv/tcg-target-has.h |  8 +++++++-
 tcg/riscv/tcg-target.c.inc | 13 +++++++++++--
 2 files changed, 18 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/tcg/riscv/tcg-target-has.h b/tcg/riscv/tcg-target-has.h
index 10e61edc45..ea38ee5cbb 100644
--- a/tcg/riscv/tcg-target-has.h
+++ b/tcg/riscv/tcg-target-has.h
@@ -64,7 +64,13 @@  tcg_target_extract_valid(TCGType type, unsigned ofs, unsigned len)
         /* ofs > 0 uses SRLIW; ofs == 0 uses add.uw. */
         return ofs || (cpuinfo & CPUINFO_ZBA);
     }
-    return (cpuinfo & CPUINFO_ZBB) && ofs == 0 && len == 16;
+    switch (len) {
+    case 1:
+        return (cpuinfo & CPUINFO_ZBS) && ofs != 0;
+    case 16:
+        return (cpuinfo & CPUINFO_ZBB) && ofs == 0;
+    }
+    return false;
 }
 #define TCG_TARGET_extract_valid  tcg_target_extract_valid
 
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 12c3cffcc0..83ec7cd980 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -162,6 +162,7 @@  typedef enum {
     OPC_ANDI = 0x7013,
     OPC_AUIPC = 0x17,
     OPC_BEQ = 0x63,
+    OPC_BEXTI = 0x48005013,
     OPC_BGE = 0x5063,
     OPC_BGEU = 0x7063,
     OPC_BLT = 0x4063,
@@ -2307,9 +2308,17 @@  static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
             } else {
                 tcg_out_opc_imm(s, OPC_SRLIW, a0, a1, a2);
             }
-        } else if (a2 == 0 && args[3] == 16) {
+            break;
+        }
+        switch (args[3]) {
+        case 1:
+            tcg_out_opc_imm(s, OPC_BEXTI, a0, a1, a2);
+            break;
+        case 16:
+            tcg_debug_assert(a2 == 0);
             tcg_out_ext16u(s, a0, a1);
-        } else {
+            break;
+        default:
             g_assert_not_reached();
         }
         break;