diff --git a/qemu/aarch64.h b/qemu/aarch64.h index dd426fdb..eeb3393e 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -2961,6 +2961,8 @@ #define tcg_const_zeros_vec tcg_const_zeros_vec_aarch64 #define tcg_const_zeros_vec_matching tcg_const_zeros_vec_matching_aarch64 #define tcg_constant_folding tcg_constant_folding_aarch64 +#define tcg_constant_internal tcg_constant_internal_aarch64 +#define tcg_constant_vec tcg_constant_vec_aarch64 #define tcg_context_init tcg_context_init_aarch64 #define tcg_cpu_exec tcg_cpu_exec_aarch64 #define tcg_current_code_size tcg_current_code_size_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index 3112ce41..3201d858 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -2961,6 +2961,8 @@ #define tcg_const_zeros_vec tcg_const_zeros_vec_aarch64eb #define tcg_const_zeros_vec_matching tcg_const_zeros_vec_matching_aarch64eb #define tcg_constant_folding tcg_constant_folding_aarch64eb +#define tcg_constant_internal tcg_constant_internal_aarch64eb +#define tcg_constant_vec tcg_constant_vec_aarch64eb #define tcg_context_init tcg_context_init_aarch64eb #define tcg_cpu_exec tcg_cpu_exec_aarch64eb #define tcg_current_code_size tcg_current_code_size_aarch64eb diff --git a/qemu/arm.h b/qemu/arm.h index 87173bda..b674c3a4 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -2961,6 +2961,8 @@ #define tcg_const_zeros_vec tcg_const_zeros_vec_arm #define tcg_const_zeros_vec_matching tcg_const_zeros_vec_matching_arm #define tcg_constant_folding tcg_constant_folding_arm +#define tcg_constant_internal tcg_constant_internal_arm +#define tcg_constant_vec tcg_constant_vec_arm #define tcg_context_init tcg_context_init_arm #define tcg_cpu_exec tcg_cpu_exec_arm #define tcg_current_code_size tcg_current_code_size_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index af9fb6c8..69175a98 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -2961,6 +2961,8 @@ #define tcg_const_zeros_vec tcg_const_zeros_vec_armeb #define tcg_const_zeros_vec_matching tcg_const_zeros_vec_matching_armeb #define tcg_constant_folding tcg_constant_folding_armeb +#define tcg_constant_internal tcg_constant_internal_armeb +#define tcg_constant_vec tcg_constant_vec_armeb #define tcg_context_init tcg_context_init_armeb #define tcg_cpu_exec tcg_cpu_exec_armeb #define tcg_current_code_size tcg_current_code_size_armeb diff --git a/qemu/glib_compat.c b/qemu/glib_compat.c index 3f11020c..4c1c5d9a 100644 --- a/qemu/glib_compat.c +++ b/qemu/glib_compat.c @@ -193,6 +193,48 @@ gboolean g_int_equal(gconstpointer v1, gconstpointer v2) return *((const gint*)v1) == *((const gint*)v2); } +/** + * g_int64_hash: + * @v: a pointer to a #gint64 key + * + * Converts a pointer to a #gint64 to a hash value. + * + * It can be passed to g_hash_table_new() as the @hash_func parameter, + * when using non-%NULL pointers to 64-bit integer values as keys in a + * #GHashTable. + * + * Returns: a hash value corresponding to the key. + * + * Since: 2.22 + */ +guint +g_int64_hash (gconstpointer v) +{ + return (guint) *(const gint64*) v; +} + +/** + * g_int64_equal: + * @v1: a pointer to a #gint64 key + * @v2: a pointer to a #gint64 key to compare with @v1 + * + * Compares the two #gint64 values being pointed to and returns + * %TRUE if they are equal. + * It can be passed to g_hash_table_new() as the @key_equal_func + * parameter, when using non-%NULL pointers to 64-bit integers as keys in a + * #GHashTable. + * + * Returns: %TRUE if the two keys match. + * + * Since: 2.22 + */ +gboolean +g_int64_equal (gconstpointer v1, + gconstpointer v2) +{ + return *((const gint64*) v1) == *((const gint64*) v2); +} + /* Doubly-linked list */ GList *g_list_first(GList *list) diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 8626d469..14a01336 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -2967,6 +2967,8 @@ symbols = ( 'tcg_const_zeros_vec', 'tcg_const_zeros_vec_matching', 'tcg_constant_folding', + 'tcg_constant_internal', + 'tcg_constant_vec', 'tcg_context_init', 'tcg_cpu_exec', 'tcg_current_code_size', diff --git a/qemu/include/glib_compat.h b/qemu/include/glib_compat.h index dd8a1a73..e6476044 100644 --- a/qemu/include/glib_compat.h +++ b/qemu/include/glib_compat.h @@ -40,6 +40,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. typedef void* gpointer; typedef const void *gconstpointer; typedef int gint; +typedef int32_t gint32; +typedef int64_t gint64; typedef uint32_t guint32; typedef uint64_t guint64; typedef unsigned int guint; @@ -68,6 +70,9 @@ gboolean g_str_has_prefix(const gchar *str, const gchar *prefix); guint g_int_hash(gconstpointer v); gboolean g_int_equal(gconstpointer v1, gconstpointer v2); +guint g_int64_hash(gconstpointer v); +gboolean g_int64_equal(gconstpointer v1, gconstpointer v2); + typedef struct _GList { gpointer data; struct _GList *next; diff --git a/qemu/m68k.h b/qemu/m68k.h index 98e2c08c..c64a9551 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -2961,6 +2961,8 @@ #define tcg_const_zeros_vec tcg_const_zeros_vec_m68k #define tcg_const_zeros_vec_matching tcg_const_zeros_vec_matching_m68k #define tcg_constant_folding tcg_constant_folding_m68k +#define tcg_constant_internal tcg_constant_internal_m68k +#define tcg_constant_vec tcg_constant_vec_m68k #define tcg_context_init tcg_context_init_m68k #define tcg_cpu_exec tcg_cpu_exec_m68k #define tcg_current_code_size tcg_current_code_size_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 82ec2c2a..a3a520b1 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -2961,6 +2961,8 @@ #define tcg_const_zeros_vec tcg_const_zeros_vec_mips #define tcg_const_zeros_vec_matching tcg_const_zeros_vec_matching_mips #define tcg_constant_folding tcg_constant_folding_mips +#define tcg_constant_internal tcg_constant_internal_mips +#define tcg_constant_vec tcg_constant_vec_mips #define tcg_context_init tcg_context_init_mips #define tcg_cpu_exec tcg_cpu_exec_mips #define tcg_current_code_size tcg_current_code_size_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 867ed00f..968c648a 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -2961,6 +2961,8 @@ #define tcg_const_zeros_vec tcg_const_zeros_vec_mips64 #define tcg_const_zeros_vec_matching tcg_const_zeros_vec_matching_mips64 #define tcg_constant_folding tcg_constant_folding_mips64 +#define tcg_constant_internal tcg_constant_internal_mips64 +#define tcg_constant_vec tcg_constant_vec_mips64 #define tcg_context_init tcg_context_init_mips64 #define tcg_cpu_exec tcg_cpu_exec_mips64 #define tcg_current_code_size tcg_current_code_size_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 06187b7f..20054641 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -2961,6 +2961,8 @@ #define tcg_const_zeros_vec tcg_const_zeros_vec_mips64el #define tcg_const_zeros_vec_matching tcg_const_zeros_vec_matching_mips64el #define tcg_constant_folding tcg_constant_folding_mips64el +#define tcg_constant_internal tcg_constant_internal_mips64el +#define tcg_constant_vec tcg_constant_vec_mips64el #define tcg_context_init tcg_context_init_mips64el #define tcg_cpu_exec tcg_cpu_exec_mips64el #define tcg_current_code_size tcg_current_code_size_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 33a6693a..0fc32a72 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -2961,6 +2961,8 @@ #define tcg_const_zeros_vec tcg_const_zeros_vec_mipsel #define tcg_const_zeros_vec_matching tcg_const_zeros_vec_matching_mipsel #define tcg_constant_folding tcg_constant_folding_mipsel +#define tcg_constant_internal tcg_constant_internal_mipsel +#define tcg_constant_vec tcg_constant_vec_mipsel #define tcg_context_init tcg_context_init_mipsel #define tcg_cpu_exec tcg_cpu_exec_mipsel #define tcg_current_code_size tcg_current_code_size_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index af22b1ac..05694152 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -2961,6 +2961,8 @@ #define tcg_const_zeros_vec tcg_const_zeros_vec_powerpc #define tcg_const_zeros_vec_matching tcg_const_zeros_vec_matching_powerpc #define tcg_constant_folding tcg_constant_folding_powerpc +#define tcg_constant_internal tcg_constant_internal_powerpc +#define tcg_constant_vec tcg_constant_vec_powerpc #define tcg_context_init tcg_context_init_powerpc #define tcg_cpu_exec tcg_cpu_exec_powerpc #define tcg_current_code_size tcg_current_code_size_powerpc diff --git a/qemu/riscv32.h b/qemu/riscv32.h index 53a11679..d3efb27c 100644 --- a/qemu/riscv32.h +++ b/qemu/riscv32.h @@ -2961,6 +2961,8 @@ #define tcg_const_zeros_vec tcg_const_zeros_vec_riscv32 #define tcg_const_zeros_vec_matching tcg_const_zeros_vec_matching_riscv32 #define tcg_constant_folding tcg_constant_folding_riscv32 +#define tcg_constant_internal tcg_constant_internal_riscv32 +#define tcg_constant_vec tcg_constant_vec_riscv32 #define tcg_context_init tcg_context_init_riscv32 #define tcg_cpu_exec tcg_cpu_exec_riscv32 #define tcg_current_code_size tcg_current_code_size_riscv32 diff --git a/qemu/riscv64.h b/qemu/riscv64.h index 5492f4d2..ad463f54 100644 --- a/qemu/riscv64.h +++ b/qemu/riscv64.h @@ -2961,6 +2961,8 @@ #define tcg_const_zeros_vec tcg_const_zeros_vec_riscv64 #define tcg_const_zeros_vec_matching tcg_const_zeros_vec_matching_riscv64 #define tcg_constant_folding tcg_constant_folding_riscv64 +#define tcg_constant_internal tcg_constant_internal_riscv64 +#define tcg_constant_vec tcg_constant_vec_riscv64 #define tcg_context_init tcg_context_init_riscv64 #define tcg_cpu_exec tcg_cpu_exec_riscv64 #define tcg_current_code_size tcg_current_code_size_riscv64 diff --git a/qemu/sparc.h b/qemu/sparc.h index 87919cc0..777c6f6c 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -2961,6 +2961,8 @@ #define tcg_const_zeros_vec tcg_const_zeros_vec_sparc #define tcg_const_zeros_vec_matching tcg_const_zeros_vec_matching_sparc #define tcg_constant_folding tcg_constant_folding_sparc +#define tcg_constant_internal tcg_constant_internal_sparc +#define tcg_constant_vec tcg_constant_vec_sparc #define tcg_context_init tcg_context_init_sparc #define tcg_cpu_exec tcg_cpu_exec_sparc #define tcg_current_code_size tcg_current_code_size_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index e9ad7a7e..706b288c 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -2961,6 +2961,8 @@ #define tcg_const_zeros_vec tcg_const_zeros_vec_sparc64 #define tcg_const_zeros_vec_matching tcg_const_zeros_vec_matching_sparc64 #define tcg_constant_folding tcg_constant_folding_sparc64 +#define tcg_constant_internal tcg_constant_internal_sparc64 +#define tcg_constant_vec tcg_constant_vec_sparc64 #define tcg_context_init tcg_context_init_sparc64 #define tcg_cpu_exec tcg_cpu_exec_sparc64 #define tcg_current_code_size tcg_current_code_size_sparc64 diff --git a/qemu/tcg/optimize.c b/qemu/tcg/optimize.c index 2e61b9b1..0bb649e8 100644 --- a/qemu/tcg/optimize.c +++ b/qemu/tcg/optimize.c @@ -104,6 +104,17 @@ static void init_ts_info(TCGContext *s, TCGTemp *ts) ti->prev_copy = ts; ti->is_const = false; ti->mask = -1; + if (ts->kind == TEMP_CONST) { + ti->is_const = true; + ti->val = ti->mask = ts->val; + if (TCG_TARGET_REG_BITS > 32 && ts->type == TCG_TYPE_I32) { + /* High bits of a 32-bit quantity are garbage. */ + ti->mask |= ~0xffffffffull; + } + } else { + ti->is_const = false; + ti->mask = -1; + } set_bit(idx, temps_used->l); } } diff --git a/qemu/tcg/tcg.c b/qemu/tcg/tcg.c index a40f8c14..660d326e 100644 --- a/qemu/tcg/tcg.c +++ b/qemu/tcg/tcg.c @@ -523,6 +523,13 @@ void tcg_func_start(TCGContext *s) /* No temps have been previously allocated for size or locality. */ memset(s->free_temps, 0, sizeof(s->free_temps)); + /* No constant temps have been previously allocated. */ + for (int i = 0; i < TCG_TYPE_COUNT; ++i) { + if (s->const_table[i]) { + g_hash_table_remove_all(s->const_table[i]); + } + } + s->nb_ops = 0; s->nb_labels = 0; s->current_frame_offset = s->frame_start; @@ -616,13 +623,19 @@ TCGTemp *tcg_global_mem_new_internal(TCGContext *s, TCGType type, TCGv_ptr base, bigendian = 1; #endif - if (base_ts->kind != TEMP_FIXED) { + switch (base_ts->kind) { + case TEMP_FIXED: + break; + case TEMP_GLOBAL: /* We do not support double-indirect registers. */ tcg_debug_assert(!base_ts->indirect_reg); base_ts->indirect_base = 1; s->nb_indirects += (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64 ? 2 : 1); indirect_reg = 1; + break; + default: + g_assert_not_reached(); } if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) { @@ -745,6 +758,11 @@ void tcg_temp_free_internal(TCGContext *s, TCGTemp *ts) { int k, idx; + /* In order to simplify users of tcg_constant_*, silently ignore free. */ + if (ts->kind == TEMP_CONST) { + return; + } + #if defined(CONFIG_DEBUG_TCG) s->temps_in_use--; if (s->temps_in_use < 0) { @@ -761,6 +779,59 @@ void tcg_temp_free_internal(TCGContext *s, TCGTemp *ts) set_bit(idx, s->free_temps[k].l); } +TCGTemp *tcg_constant_internal(TCGContext *s, TCGType type, int64_t val) +{ + GHashTable *h = s->const_table[type]; + TCGTemp *ts; + + if (h == NULL) { + h = g_hash_table_new(g_int64_hash, g_int64_equal); + s->const_table[type] = h; + } + + ts = g_hash_table_lookup(h, &val); + if (ts == NULL) { + ts = tcg_temp_alloc(s); + + if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) { + TCGTemp *ts2 = tcg_temp_alloc(s); + + ts->base_type = TCG_TYPE_I64; + ts->type = TCG_TYPE_I32; + ts->kind = TEMP_CONST; + ts->temp_allocated = 1; + /* + * Retain the full value of the 64-bit constant in the low + * part, so that the hash table works. Actual uses will + * truncate the value to the low part. + */ + ts->val = val; + + tcg_debug_assert(ts2 == ts + 1); + ts2->base_type = TCG_TYPE_I64; + ts2->type = TCG_TYPE_I32; + ts2->kind = TEMP_CONST; + ts2->temp_allocated = 1; + ts2->val = val >> 32; + } else { + ts->base_type = type; + ts->type = type; + ts->kind = TEMP_CONST; + ts->temp_allocated = 1; + ts->val = val; + } + g_hash_table_insert(h, &ts->val, ts); + } + + return ts; +} + +TCGv_vec tcg_constant_vec(TCGContext *s, TCGType type, unsigned vece, int64_t val) +{ + val = dup_const(vece, val); + return temp_tcgv_vec(s, tcg_constant_internal(s, type, val)); +} + TCGv_i32 tcg_const_i32(TCGContext *s, int32_t val) { TCGv_i32 t0; @@ -1287,6 +1358,9 @@ static void tcg_reg_alloc_start(TCGContext *s) TCGTempVal val = TEMP_VAL_MEM; switch (ts->kind) { + case TEMP_CONST: + val = TEMP_VAL_CONST; + break; case TEMP_FIXED: val = TEMP_VAL_REG; break; @@ -1323,6 +1397,26 @@ static char *tcg_get_arg_str_ptr(TCGContext *s, char *buf, int buf_size, case TEMP_NORMAL: snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals); break; + case TEMP_CONST: + switch (ts->type) { + case TCG_TYPE_I32: + snprintf(buf, buf_size, "$0x%x", (int32_t)ts->val); + break; +#if TCG_TARGET_REG_BITS > 32 + case TCG_TYPE_I64: + snprintf(buf, buf_size, "$0x%" PRIx64, ts->val); + break; +#endif + case TCG_TYPE_V64: + case TCG_TYPE_V128: + case TCG_TYPE_V256: + snprintf(buf, buf_size, "v%d$0x%" PRIx64, + 64 << (ts->type - TCG_TYPE_V64), ts->val); + break; + default: + g_assert_not_reached(); + } + break; } return buf; } @@ -1924,6 +2018,7 @@ static void la_bb_end(TCGContext *s, int ng, int nt) state = TS_DEAD | TS_MEM; break; case TEMP_NORMAL: + case TEMP_CONST: state = TS_DEAD; break; default: @@ -2605,15 +2700,28 @@ static void temp_load(TCGContext *, TCGTemp *, TCGRegSet, TCGRegSet, TCGRegSet); mark it free; otherwise mark it dead. */ static void temp_free_or_dead(TCGContext *s, TCGTemp *ts, int free_or_dead) { - if (temp_readonly(ts)) { + TCGTempVal new_type; + + switch (ts->kind) { + case TEMP_FIXED: return; + case TEMP_GLOBAL: + case TEMP_LOCAL: + new_type = TEMP_VAL_MEM; + break; + case TEMP_NORMAL: + new_type = free_or_dead < 0 ? TEMP_VAL_MEM : TEMP_VAL_DEAD; + break; + case TEMP_CONST: + new_type = TEMP_VAL_CONST; + break; + default: + g_assert_not_reached(); } if (ts->val_type == TEMP_VAL_REG) { s->reg_to_temp[ts->reg] = NULL; } - ts->val_type = (free_or_dead < 0 - || ts->kind != TEMP_NORMAL - ? TEMP_VAL_MEM : TEMP_VAL_DEAD); + ts->val_type = new_type; } /* Mark a temporary as dead. */ @@ -2629,10 +2737,7 @@ static inline void temp_dead(TCGContext *s, TCGTemp *ts) static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs, TCGRegSet preferred_regs, int free_or_dead) { - if (temp_readonly(ts)) { - return; - } - if (!ts->mem_coherent) { + if (!temp_readonly(ts) && !ts->mem_coherent) { if (!ts->mem_allocated) { temp_allocate_frame(s, ts); } @@ -2850,12 +2955,22 @@ static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs) for (i = s->nb_globals; i < s->nb_temps; i++) { TCGTemp *ts = &s->temps[i]; - if (ts->kind == TEMP_LOCAL) { + + switch (ts->kind) { + case TEMP_LOCAL: temp_save(s, ts, allocated_regs); - } else { + break; + case TEMP_NORMAL: /* The liveness analysis already ensures that temps are dead. Keep an tcg_debug_assert for safety. */ tcg_debug_assert(ts->val_type == TEMP_VAL_DEAD); + break; + case TEMP_CONST: + /* Similarly, we should have freed any allocated register. */ + tcg_debug_assert(ts->val_type == TEMP_VAL_CONST); + break; + default: + g_assert_not_reached(); } } @@ -3121,14 +3236,14 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) nb_iargs = def->nb_iargs; /* copy constants */ - memcpy(new_args + nb_oargs + nb_iargs, + memcpy(new_args + nb_oargs + nb_iargs, op->args + nb_oargs + nb_iargs, sizeof(TCGArg) * def->nb_cargs); i_allocated_regs = s->reserved_regs; o_allocated_regs = s->reserved_regs; - /* satisfy input constraints */ + /* satisfy input constraints */ for (k = 0; k < nb_iargs; k++) { TCGRegSet i_preferred_regs, o_preferred_regs; @@ -3148,45 +3263,41 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) i_preferred_regs = o_preferred_regs = 0; if (arg_ct->ialias) { o_preferred_regs = op->output_pref[arg_ct->alias_index]; - if (ts->kind == TEMP_FIXED) { - /* if fixed register, we must allocate a new register - if the alias is not the same register */ - if (arg != op->args[arg_ct->alias_index]) { - goto allocate_in_reg; - } - } else { - /* if the input is aliased to an output and if it is - not dead after the instruction, we must allocate - a new register and move it */ - if (!IS_DEAD_ARG(i)) { - goto allocate_in_reg; - } + /* + * If the input is readonly, then it cannot also be an + * output and aliased to itself. If the input is not + * dead after the instruction, we must allocate a new + * register and move it. + */ + if (temp_readonly(ts) || !IS_DEAD_ARG(i)) { + goto allocate_in_reg; + } - /* check if the current register has already been allocated - for another input aliased to an output */ - if (ts->val_type == TEMP_VAL_REG) { - int k2, i2; - reg = ts->reg; - for (k2 = 0 ; k2 < k ; k2++) { - i2 = def->args_ct[nb_oargs + k2].sort_index; - if (def->args_ct[i2].ialias && reg == new_args[i2]) { - goto allocate_in_reg; - } + /* + * Check if the current register has already been allocated + * for another input aliased to an output. + */ + if (ts->val_type == TEMP_VAL_REG) { + reg = ts->reg; + for (int k2 = 0; k2 < k; k2++) { + int i2 = def->args_ct[nb_oargs + k2].sort_index; + if (def->args_ct[i2].ialias && reg == new_args[i2]) { + goto allocate_in_reg; } } - i_preferred_regs = o_preferred_regs; } + i_preferred_regs = o_preferred_regs; } temp_load(s, ts, arg_ct->regs, i_allocated_regs, i_preferred_regs); reg = ts->reg; - if (tcg_regset_test_reg(arg_ct->regs, reg)) { - /* nothing to do : the constraint is satisfied */ - } else { - allocate_in_reg: - /* allocate a new register matching the constraint - and move the temporary register into it */ + if (!tcg_regset_test_reg(arg_ct->regs, reg)) { + allocate_in_reg: + /* + * Allocate a new register matching the constraint + * and move the temporary register into it. + */ temp_load(s, ts, s->tcg_target_available_regs[ts->type], i_allocated_regs, 0); reg = tcg_reg_alloc(s, arg_ct->regs, i_allocated_regs, diff --git a/qemu/tcg/tcg.h b/qemu/tcg/tcg.h index 09da7b19..3344de85 100644 --- a/qemu/tcg/tcg.h +++ b/qemu/tcg/tcg.h @@ -499,6 +499,8 @@ typedef enum TCGTempKind { TEMP_GLOBAL, /* Temp is in a fixed register. */ TEMP_FIXED, + /* Temp is a fixed constant. */ + TEMP_CONST, } TCGTempKind; typedef struct TCGTemp { @@ -735,6 +737,7 @@ struct TCGContext { struct TCGLabelPoolData *pool_labels; #endif + GHashTable *const_table[TCG_TYPE_COUNT]; TCGTempSet free_temps[TCG_TYPE_COUNT * 2]; TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */ @@ -877,7 +880,7 @@ struct TCGContext { static inline bool temp_readonly(TCGTemp *ts) { - return ts->kind == TEMP_FIXED; + return ts->kind >= TEMP_FIXED; } static inline size_t temp_idx(TCGContext *tcg_ctx, TCGTemp *ts) @@ -1140,6 +1143,7 @@ static inline void *tcg_malloc(TCGContext *s, int size) } } +/* Allocate a new temporary and initialize it with a constant. */ TCGv_i32 tcg_const_i32(TCGContext *s, int32_t val); TCGv_i64 tcg_const_i64(TCGContext *s, int64_t val); TCGv_i32 tcg_const_local_i32(TCGContext *s, int32_t val); @@ -1149,6 +1153,24 @@ TCGv_vec tcg_const_ones_vec(TCGContext *s, TCGType); TCGv_vec tcg_const_zeros_vec_matching(TCGContext *s, TCGv_vec); TCGv_vec tcg_const_ones_vec_matching(TCGContext *s, TCGv_vec); +/* + * Locate or create a read-only temporary that is a constant. + * This kind of temporary need not and should not be freed. + */ +TCGTemp *tcg_constant_internal(TCGContext *s, TCGType type, int64_t val); + +static inline TCGv_i32 tcg_constant_i32(TCGContext *s, int32_t val) +{ + return temp_tcgv_i32(s, tcg_constant_internal(s, TCG_TYPE_I32, val)); +} + +static inline TCGv_i64 tcg_constant_i64(TCGContext *s, int64_t val) +{ + return temp_tcgv_i64(s, tcg_constant_internal(s, TCG_TYPE_I64, val)); +} + +TCGv_vec tcg_constant_vec(TCGContext *s, TCGType type, unsigned vece, int64_t val); + #if UINTPTR_MAX == UINT32_MAX # define tcg_const_ptr(t, x) ((TCGv_ptr)tcg_const_i32((t), (intptr_t)(x))) # define tcg_const_local_ptr(t, x) ((TCGv_ptr)tcg_const_local_i32((t), (intptr_t)(x))) diff --git a/qemu/x86_64.h b/qemu/x86_64.h index c8d26b7b..ff1f7a59 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -2961,6 +2961,8 @@ #define tcg_const_zeros_vec tcg_const_zeros_vec_x86_64 #define tcg_const_zeros_vec_matching tcg_const_zeros_vec_matching_x86_64 #define tcg_constant_folding tcg_constant_folding_x86_64 +#define tcg_constant_internal tcg_constant_internal_x86_64 +#define tcg_constant_vec tcg_constant_vec_x86_64 #define tcg_context_init tcg_context_init_x86_64 #define tcg_cpu_exec tcg_cpu_exec_x86_64 #define tcg_current_code_size tcg_current_code_size_x86_64