git subrepo pull (merge) --force deps/lightning
[pcsx_rearmed.git] / deps / lightning / include / lightning / jit_private.h
index 8c05853..a730d73 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2019  Free Software Foundation, Inc.
+ * Copyright (C) 2012-2023  Free Software Foundation, Inc.
  *
  * This file is part of GNU lightning.
  *
 #  define HIDDEN               /**/
 #endif
 
+#if PACKED_STACK || STRONG_TYPE_CHECKING
+#  define assert_arg_type(code, expect)                                        \
+    do assert((code) == (expect)); while (0)
+#  define assert_putarg_type(code, expect)                             \
+    do                                                                 \
+       assert((((code) - jit_code_putargr_c) >> 2) ==                  \
+              ((expect) - jit_code_arg_c));                            \
+    while (0)
+#else
+#  define assert_arg_type(code, expect)                                        \
+    do assert((int)(code) == (int)(expect) ||                          \
+             (code) == jit_code_arg); while (0)
+#  define assert_putarg_type(code, expect)                             \
+    do                                                                 \
+       assert(((((code) - jit_code_putargr_c) >> 2) ==                 \
+              ((expect) - jit_code_arg_c)) ||                          \
+              ((code) == jit_code_arg));                               \
+    while (0)
+#endif
+
 #define rc(value)              jit_class_##value
 #define rn(reg)                        (jit_regno(_rvs[jit_regno(reg)].spec))
 
@@ -150,6 +170,13 @@ typedef jit_uint64_t               jit_regset_t;
 #  define JIT_RET              _A0
 #  define JIT_FRET             _FA0
 typedef jit_uint64_t           jit_regset_t;
+#elif defined(__loongarch__)
+#  define JIT_RA0              _A0
+#  define JIT_FA0              _FA0
+#  define JIT_SP               _SP
+#  define JIT_RET              _A0
+#  define JIT_FRET             _FA0
+typedef jit_uint64_t           jit_regset_t;
 #endif
 
 #define jit_data(u,v,w)                _jit_data(_jit,u,v,w)
@@ -167,48 +194,104 @@ extern jit_node_t *_jit_data(jit_state_t*, const void*,
     (!jit_regset_tstbit(&_jitc->regarg, regno) &&                      \
      !jit_regset_tstbit(&_jitc->regsav, regno))
 
-#define jit_inc_synth(code)                                            \
+#define jit_code_inc_synth(code)                                       \
+    do {                                                               \
+       (void)jit_new_node(code);                                       \
+       jit_synth_inc();                                                \
+    } while (0)
+#define jit_inc_synth(name)                                            \
+    jit_code_inc_synth(jit_code_##name)
+#define jit_code_inc_synth_w(code, u)                                  \
+    do {                                                               \
+       (void)jit_new_node_w(code, u);                                  \
+       jit_synth_inc();                                                \
+    } while (0)
+#define jit_inc_synth_w(name, u)                                       \
+    jit_code_inc_synth_w(jit_code_##name, u)
+#define jit_code_inc_synth_f(code, u)                                  \
+    do {                                                               \
+       (void)jit_new_node_f(code, u);                                  \
+       jit_synth_inc();                                                \
+    } while (0)
+#define jit_inc_synth_f(name, u)                                       \
+    jit_code_inc_synth_f(jit_code_##name, u)
+#define jit_code_inc_synth_d(code, u)                                  \
+    do {                                                               \
+       (void)jit_new_node_d(code, u);                                  \
+       jit_synth_inc();                                                \
+    } while (0)
+#define jit_inc_synth_d(name, u)                                       \
+    jit_code_inc_synth_d(jit_code_##name, u)
+#define jit_code_inc_synth_ww(code, u, v)                              \
     do {                                                               \
-       (void)jit_new_node(jit_code_##code);                            \
+       (void)jit_new_node_ww(code, u, v);                              \
        jit_synth_inc();                                                \
     } while (0)
-#define jit_inc_synth_w(code, u)                                       \
+#define jit_inc_synth_ww(name, u, v)                                   \
+    jit_code_inc_synth_ww(jit_code_##name, u, v)
+#define jit_code_inc_synth_wp(code, u, v)                              \
     do {                                                               \
-       (void)jit_new_node_w(jit_code_##code, u);                       \
+       (void)jit_new_node_wp(code, u, v);                              \
        jit_synth_inc();                                                \
     } while (0)
-#define jit_inc_synth_f(code, u)                                       \
+#define jit_inc_synth_wp(name, u, v)                                   \
+    jit_code_inc_synth_wp(jit_code_##name, u, v)
+#define jit_code_inc_synth_fp(code, u, v)                              \
     do {                                                               \
-       (void)jit_new_node_f(jit_code_##code, u);                       \
+       (void)jit_new_node_fp(code, u, v);                              \
        jit_synth_inc();                                                \
     } while (0)
-#define jit_inc_synth_d(code, u)                                       \
+#define jit_inc_synth_fp(name, u, v)                                   \
+    jit_code_inc_synth_fp(jit_code_##name, u, v)
+#define jit_code_inc_synth_dp(code, u, v)                              \
     do {                                                               \
-       (void)jit_new_node_d(jit_code_##code, u);                       \
+       (void)jit_new_node_dp(code, u, v);                              \
        jit_synth_inc();                                                \
     } while (0)
-#define jit_inc_synth_ww(code, u, v)                                   \
+#define jit_inc_synth_dp(name, u, v)                                   \
+    jit_code_inc_synth_dp(jit_code_##name, u, v)
+#define jit_inc_synth_wf(name, u, v)                                   \
+    jit_code_inc_synth_wf(jit_code_##name, u, v)
+#define jit_code_inc_synth_wf(code, u, v)                              \
     do {                                                               \
-       (void)jit_new_node_ww(jit_code_##code, u, v);                   \
+       (void)jit_new_node_wf(code, u, v);                              \
        jit_synth_inc();                                                \
     } while (0)
-#define jit_inc_synth_wp(code, u, v)                                   \
+#define jit_inc_synth_wqf(name, u, v, w, x)                            \
     do {                                                               \
-       (void)jit_new_node_wp(jit_code_##code, u, v);                   \
+       (void)jit_new_node_wqf(jit_code_##name, u, v, w, x);            \
        jit_synth_inc();                                                \
     } while (0)
-#define jit_inc_synth_fp(code, u, v)                                   \
+#define jit_inc_synth_wd(name, u, v)                                   \
+    jit_code_inc_synth_wd(jit_code_##name, u, v)
+#define jit_inc_synth_wqd(name, u, v, w, x)                            \
     do {                                                               \
-       (void)jit_new_node_fp(jit_code_##code, u, v);                   \
+       (void)jit_new_node_wqd(jit_code_##name, u, v, w, x);            \
        jit_synth_inc();                                                \
     } while (0)
-#define jit_inc_synth_dp(code, u, v)                                   \
+#define jit_code_inc_synth_wd(code, u, v)                              \
     do {                                                               \
-       (void)jit_new_node_dp(jit_code_##code, u, v);                   \
+       (void)jit_new_node_wd(code, u, v);                              \
        jit_synth_inc();                                                \
     } while (0)
 #define jit_dec_synth()                jit_synth_dec()
 
+#define jit_link_alist(node)                                           \
+    do {                                                               \
+       node->link = _jitc->function->alist;                            \
+       _jitc->function->alist = node;                                  \
+    } while (0)
+#define jit_check_frame()                                              \
+    do {                                                               \
+       if (!_jitc->function->need_frame) {                             \
+           _jitc->again = 1;                                           \
+           _jitc->function->need_frame = 1;                            \
+       }                                                               \
+    } while (0)
+#define jit_diffsize() (stack_framesize - _jitc->framesize)
+#define jit_framesize()        (stack_framesize - jit_diffsize())
+#define jit_selfsize() (_jitc->function->self.size - jit_diffsize())
+
 #define jit_link_prolog()                                              \
     do {                                                               \
        _jitc->tail->link = _jitc->function->prolog->link;              \
@@ -241,8 +324,8 @@ extern jit_node_t *_jit_data(jit_state_t*, const void*,
 #define jit_class_xpr          0x80000000      /* float / vector */
 /* Used on sparc64 where %f0-%f31 can be encode for single float
  * but %f32 to %f62 only as double precision */
-#define jit_class_sng          0x10000000      /* Single precision float */
-#define jit_class_dbl          0x20000000      /* Only double precision float */
+#define jit_class_sng          0x00010000      /* Single precision float */
+#define jit_class_dbl          0x00020000      /* Only double precision float */
 #define jit_regno_patch                0x00008000      /* this is a register
                                                 * returned by a "user" call
                                                 * to jit_get_reg() */
@@ -264,17 +347,20 @@ extern jit_node_t *_jit_data(jit_state_t*, const void*,
 #define jit_cc_a0_flt          0x00000020      /* arg0 is immediate float */
 #define jit_cc_a0_dbl          0x00000040      /* arg0 is immediate double */
 #define jit_cc_a0_arg          0x00000080      /* arg1 is an argument int id */
-#define jit_cc_a1_reg          0x00000100      /* arg1 is a register */
-#define jit_cc_a1_chg          0x00000200      /* arg1 is modified */
-#define jit_cc_a1_int          0x00001000      /* arg1 is immediate word */
-#define jit_cc_a1_flt          0x00002000      /* arg1 is immediate float */
-#define jit_cc_a1_dbl          0x00004000      /* arg1 is immediate double */
-#define jit_cc_a1_arg          0x00008000      /* arg1 is an argument node */
+#define jit_cc_a0_cnd          0x00000100      /* arg1 is a conditinally set register */
+#define jit_cc_a1_reg          0x00000200      /* arg1 is a register */
+#define jit_cc_a1_chg          0x00000400      /* arg1 is modified */
+#define jit_cc_a1_int          0x00000800      /* arg1 is immediate word */
+#define jit_cc_a1_flt          0x00001000      /* arg1 is immediate float */
+#define jit_cc_a1_dbl          0x00002000      /* arg1 is immediate double */
+#define jit_cc_a1_arg          0x00004000      /* arg1 is an argument node */
+#define jit_cc_a1_rlh          0x00008000      /* arg1 is a register pair */
 #define jit_cc_a2_reg          0x00010000      /* arg2 is a register */
 #define jit_cc_a2_chg          0x00020000      /* arg2 is modified */
 #define jit_cc_a2_int          0x00100000      /* arg2 is immediate word */
 #define jit_cc_a2_flt          0x00200000      /* arg2 is immediate float */
 #define jit_cc_a2_dbl          0x00400000      /* arg2 is immediate double */
+#define jit_cc_a2_rlh          0x00800000      /* arg2 is a register pair */
 
 #if __ia64__ || (__sparc__ && __WORDSIZE == 64)
 extern void
@@ -363,6 +449,8 @@ typedef struct jit_register jit_register_t;
 #  if DISASSEMBLER
 typedef struct jit_data_info   jit_data_info_t;
 #  endif
+#elif __riscv
+typedef struct jit_const       jit_const_t;
 #endif
 
 union jit_data {
@@ -412,6 +500,9 @@ struct jit_block {
     jit_node_t         *label;
     jit_regset_t        reglive;
     jit_regset_t        regmask;
+    jit_bool_t          again;         /* Flag need to rebuild regset masks
+                                        * due to changes in live and unknown
+                                        * state. */
 };
 
 struct jit_value {
@@ -434,6 +525,12 @@ struct jit_data_info {
     jit_uword_t                  code;         /* pointer in code buffer */
     jit_word_t           length;       /* length of constant vector */
 };
+#elif __riscv && __WORDSIZE == 64
+struct jit_const {
+    jit_word_t           value;
+    jit_word_t           address;
+    jit_const_t                 *next;
+};
 #endif
 
 struct jit_function {
@@ -454,9 +551,14 @@ struct jit_function {
     } call;
     jit_node_t         *prolog;
     jit_node_t         *epilog;
+    jit_node_t         *alist;
     jit_int32_t                *regoff;
     jit_regset_t        regset;
     jit_int32_t                 stack;
+#if !defined(__arm__)
+    jit_int32_t                 cvt_offset;    /* allocai'd offset for x87<->xmm or
+                                        * fpr<->gpr transfer using the stack */
+#endif
 
     /* Helper for common jit generation pattern, used in GNU Smalltalk
      * and possibly others, where a static frame layout is required or
@@ -465,11 +567,25 @@ struct jit_function {
     jit_uint32_t        define_frame : 1;
     jit_uint32_t        assume_frame : 1;
 
+    jit_uint32_t        need_frame : 1;        /* need frame pointer? */
+    jit_uint32_t        need_stack : 1;        /* need stack pointer? */
+    jit_uint32_t        need_return : 1;       /* not a leaf function */
+
     /* alloca offset offset */
     jit_int32_t                 aoffoff;
     /* uses allocar flag */
     jit_uint32_t        allocar : 1;
 
+#if __arm__
+    /* If will, or might use float registers and vfp is not available.
+     * Use the first 64 bytes always, as the access to the virtual float
+     * registers use hardcoded instructions that can only reach 64 byte
+     * displacements, and to keep code simpler, do not use temporaries. */
+    jit_uint32_t         swf_offset : 1;
+    /* If need to call C functions for some operation, or variadic function */
+    jit_uint32_t         save_reg_args : 1;
+#endif
+
     /* varargs state offsets */
     jit_int32_t                 vaoff;         /* offset of jit_va_list */
     jit_int32_t                 vagp;          /* first gp va argument */
@@ -489,8 +605,15 @@ struct jit_compiler {
     jit_int32_t                  rout;         /* first output register */
     jit_int32_t                  breg;         /* base register for prolog/epilog */
 #endif
+#if __mips__
+    struct {
+       jit_int32_t       op;           /* pending instruction, candidate
+                                        * to be inserted in a delay slot */
+       jit_bool_t        pend;         /* non zero if need to emit op */
+    } inst;
+#endif
 #if __mips__ || __ia64__ || __alpha__ || \
-       (__sparc__ && __WORDSIZE == 64) || __riscv
+       (__sparc__ && __WORDSIZE == 64) || __riscv || __loongarch__
     jit_int32_t                  carry;
 #define jit_carry        _jitc->carry
 #endif
@@ -508,11 +631,20 @@ struct jit_compiler {
 #endif
     jit_uint32_t         no_data : 1;
     jit_uint32_t         no_note : 1;
+    /* FIXME undocumented, might be moved to a jit_cpu field or a better
+     * configuration api.
+     * These are switches to a different unld* or unst*.
+     * Defaults are the algorithms that generate shorter code*/
+    jit_uint32_t         unld_algorithm : 1;
+    jit_uint32_t         unst_algorithm : 1;
+    jit_int32_t                  framesize;    /* space for callee save registers,
+                                        * frame pointer and return address */
     jit_int32_t                  reglen;       /* number of registers */
     jit_regset_t         regarg;       /* cannot allocate */
     jit_regset_t         regsav;       /* automatic spill only once */
     jit_regset_t         reglive;      /* known live registers at some point */
     jit_regset_t         regmask;      /* register mask to update reglive */
+    jit_regset_t         explive;      /* explicitly marked as live */
     struct {
        jit_uint8_t      *end;
     } code;
@@ -593,6 +725,27 @@ struct jit_compiler {
        jit_word_t        length;
     } prolog;
     jit_bool_t           jump;
+#elif __riscv && __WORDSIZE == 64
+    struct {
+       /* Hash table for constants to be resolved and patched */
+       struct {
+           jit_const_t **table;        /* very simple hash table */
+           jit_word_t    size;         /* number of vectors in table */
+           jit_word_t    count;        /* number of distinct entries */
+       } hash;
+       struct {
+           jit_const_t **ptr;          /* keep a single pointer */
+           jit_const_t  *list;         /* free list */
+           jit_word_t    length;       /* length of pool */
+       } pool;
+       /* Linear list for constants that cannot be encoded easily */
+       struct {
+           jit_word_t   *instrs;       /* list of direct movi instructions */
+           jit_word_t   *values;       /* list of direct movi constants */
+           jit_word_t    offset;       /* offset in instrs/values vector */
+           jit_word_t    length;       /* length of instrs/values vector */
+       } vector;
+    } consts;
 #endif
 #if GET_JIT_SIZE
     /* Temporary storage to calculate instructions length */
@@ -616,6 +769,8 @@ struct jit_state {
     struct {
        jit_uint8_t     *ptr;
        jit_word_t       length;
+        /* PROTECTED bytes starting at PTR are mprotect'd. */
+        jit_word_t       protect;
     } code;
     struct {
        jit_uint8_t     *ptr;
@@ -672,14 +827,6 @@ _jit_regarg_set(jit_state_t*, jit_node_t*, jit_int32_t);
 extern void
 _jit_regarg_clr(jit_state_t*, jit_node_t*, jit_int32_t);
 
-#define jit_get_reg(s)         _jit_get_reg(_jit,s)
-extern jit_int32_t
-_jit_get_reg(jit_state_t*, jit_int32_t);
-
-#define jit_unget_reg(r)       _jit_unget_reg(_jit,r)
-extern void
-_jit_unget_reg(jit_state_t*, jit_int32_t);
-
 #define jit_save(reg)          _jit_save(_jit, reg)
 extern void
 _jit_save(jit_state_t*, jit_int32_t);
@@ -726,7 +873,8 @@ _emit_ldxi_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
 extern void
 _emit_stxi_d(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
 
-extern void jit_init_debug(const char*);
+extern void jit_init_print(FILE*);
+extern void jit_init_debug(const char*, FILE*);
 extern void jit_finish_debug(void);
 
 extern void jit_init_note(void);