diff mbox series

[RFC,v2,16/39] target/i386: introduce instruction operand infrastructure

Message ID 20190810041255.6820-17-jan.bobek@gmail.com
State New
Headers show
Series rewrite MMX/SSE instruction translation | expand

Commit Message

Jan Bobek Aug. 10, 2019, 4:12 a.m. UTC
insnop_t and the init, prepare and finalize functions form the basis
of instruction operand decoding. Introduce macros for defining a
generic instruction operand; use cases for operand decoding will be
introduced later with instruction translators.

Signed-off-by: Jan Bobek <jan.bobek@gmail.com>
---
 target/i386/translate.c | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

Comments

Richard Henderson Aug. 13, 2019, 6:07 a.m. UTC | #1
On 8/10/19 5:12 AM, Jan Bobek wrote:
> +#define INSNOP_INIT(opT, init_stmt)                                \
> +    static int insnop_init(opT)(CPUX86State *env, DisasContext *s, \
> +                                int modrm, insnop_t(opT) *op)      \
> +    {                                                              \
> +        init_stmt;                                                 \
> +    }
...
> +#define INSNOP_INIT_FAIL        return 1
> +#define INSNOP_INIT_OK(x)       return ((*(op) = (x)), 0)

Return bool and true on success.


r~
Jan Bobek Aug. 15, 2019, midnight UTC | #2
On 8/13/19 2:07 AM, Richard Henderson wrote:
> On 8/10/19 5:12 AM, Jan Bobek wrote:
>> +#define INSNOP_INIT(opT, init_stmt)                                \
>> +    static int insnop_init(opT)(CPUX86State *env, DisasContext *s, \
>> +                                int modrm, insnop_t(opT) *op)      \
>> +    {                                                              \
>> +        init_stmt;                                                 \
>> +    }
> ...
>> +#define INSNOP_INIT_FAIL        return 1
>> +#define INSNOP_INIT_OK(x)       return ((*(op) = (x)), 0)
> 
> Return bool and true on success.

So, the reason why I did this "inverted" logic (0 = success, 1 =
failure) is because I was anticipating I might need to differentiate
between two or more different failures, in which case returning
different non-zero values for different error cases makes perfect
sense. I have not made use of it yet, but I'd rather hold on to this
idiom at least for now, until I am 100 % sure it really is
unnecessary.

-Jan
Richard Henderson Aug. 15, 2019, 9:09 a.m. UTC | #3
On 8/15/19 1:00 AM, Jan Bobek wrote:
> On 8/13/19 2:07 AM, Richard Henderson wrote:
>> On 8/10/19 5:12 AM, Jan Bobek wrote:
>>> +#define INSNOP_INIT(opT, init_stmt)                                \
>>> +    static int insnop_init(opT)(CPUX86State *env, DisasContext *s, \
>>> +                                int modrm, insnop_t(opT) *op)      \
>>> +    {                                                              \
>>> +        init_stmt;                                                 \
>>> +    }
>> ...
>>> +#define INSNOP_INIT_FAIL        return 1
>>> +#define INSNOP_INIT_OK(x)       return ((*(op) = (x)), 0)
>>
>> Return bool and true on success.
> 
> So, the reason why I did this "inverted" logic (0 = success, 1 =
> failure) is because I was anticipating I might need to differentiate
> between two or more different failures, in which case returning
> different non-zero values for different error cases makes perfect
> sense. I have not made use of it yet, but I'd rather hold on to this
> idiom at least for now, until I am 100 % sure it really is
> unnecessary.

In that case "int" still isn't the best return type -- an enumeration would be.


r~
diff mbox series

Patch

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 508d584584..109e4922eb 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4545,6 +4545,47 @@  static int ck_cpuid(CPUX86State *env, DisasContext *s, int ck_cpuid_feat)
     }
 }
 
+/*
+ * Core instruction operand infrastructure
+ */
+#define insnop_t(opT)        insnop_ ## opT ## _t
+#define insnop_init(opT)     insnop_ ## opT ## _init
+#define insnop_prepare(opT)  insnop_ ## opT ## _prepare
+#define insnop_finalize(opT) insnop_ ## opT ## _finalize
+
+#define TYPEDEF_INSNOP_T(opT, type)             \
+    typedef type insnop_t(opT);
+#define INSNOP_INIT(opT, init_stmt)                                \
+    static int insnop_init(opT)(CPUX86State *env, DisasContext *s, \
+                                int modrm, insnop_t(opT) *op)      \
+    {                                                              \
+        init_stmt;                                                 \
+    }
+#define INSNOP_PREPARE(opT, prepare_stmt)                               \
+    static void insnop_prepare(opT)(CPUX86State *env, DisasContext *s,  \
+                                    int modrm, insnop_t(opT) *op)       \
+    {                                                                   \
+        prepare_stmt;                                                   \
+    }
+#define INSNOP_FINALIZE(opT, finalize_stmt)                             \
+    static void insnop_finalize(opT)(CPUX86State *env, DisasContext *s, \
+                                     int modrm, insnop_t(opT) *op)      \
+    {                                                                   \
+        finalize_stmt;                                                  \
+    }
+#define INSNOP(opT, type, init_stmt, prepare_stmt, finalize_stmt)       \
+    TYPEDEF_INSNOP_T(opT, type)                                         \
+    INSNOP_INIT(opT, init_stmt)                                         \
+    INSNOP_PREPARE(opT, prepare_stmt)                                   \
+    INSNOP_FINALIZE(opT, finalize_stmt)
+
+#define INSNOP_INIT_FAIL        return 1
+#define INSNOP_INIT_OK(x)       return ((*(op) = (x)), 0)
+#define INSNOP_PREPARE_NOOP     /* no-op */
+#define INSNOP_PREPARE_INVALID  g_assert_not_reached()
+#define INSNOP_FINALIZE_NOOP    /* no-op */
+#define INSNOP_FINALIZE_INVALID g_assert_not_reached()
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
     enum {