mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-22 14:45:35 +00:00
tcg: Introduce TYPE_CONST temporaries
These will hold a single constant for the duration of the TB. They are hashed, so that each value has one temp across the TB. Not used yet, this is all infrastructure. Backports c0522136adf550c7a0ef7c0755c1f9d1560d2757
This commit is contained in:
parent
6100deaffd
commit
8edc9b76dd
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
197
qemu/tcg/tcg.c
197
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,
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue