tcg: Combine dh_is_64bit and dh_is_signed to dh_typecode

We will shortly be interested in distinguishing pointers
from integers in the helper's declaration, as well as a
true void return.  We currently have two parallel 1 bit
fields; merge them and expand to a 3 bit field.

Our current maximum is 7 helper arguments, plus the return
makes 8 * 3 = 24 bits used within the uint32_t typemask.

Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2021-03-18 10:01:01 -06:00
parent 3ccf6cd0e3
commit 7319d83a73
7 changed files with 67 additions and 85 deletions

View File

@ -85,32 +85,14 @@
#define dh_retvar_ptr tcgv_ptr_temp(retval) #define dh_retvar_ptr tcgv_ptr_temp(retval)
#define dh_retvar(t) glue(dh_retvar_, dh_alias(t)) #define dh_retvar(t) glue(dh_retvar_, dh_alias(t))
#define dh_is_64bit_void 0 #define dh_typecode_void 0
#define dh_is_64bit_noreturn 0 #define dh_typecode_noreturn 0
#define dh_is_64bit_i32 0 #define dh_typecode_i32 2
#define dh_is_64bit_i64 1 #define dh_typecode_s32 3
#define dh_is_64bit_ptr (sizeof(void *) == 8) #define dh_typecode_i64 4
#define dh_is_64bit_cptr dh_is_64bit_ptr #define dh_typecode_s64 5
#define dh_is_64bit(t) glue(dh_is_64bit_, dh_alias(t)) #define dh_typecode_ptr 6
#define dh_typecode(t) glue(dh_typecode_, dh_alias(t))
#define dh_is_signed_void 0
#define dh_is_signed_noreturn 0
#define dh_is_signed_i32 0
#define dh_is_signed_s32 1
#define dh_is_signed_i64 0
#define dh_is_signed_s64 1
#define dh_is_signed_f16 0
#define dh_is_signed_f32 0
#define dh_is_signed_f64 0
#define dh_is_signed_tl 0
#define dh_is_signed_int 1
/* ??? This is highly specific to the host cpu. There are even special
extension instructions that may be required, e.g. ia64's addp4. But
for now we don't support any 64-bit targets with 32-bit pointers. */
#define dh_is_signed_ptr 0
#define dh_is_signed_cptr dh_is_signed_ptr
#define dh_is_signed_env dh_is_signed_ptr
#define dh_is_signed(t) dh_is_signed_##t
#define dh_callflag_i32 0 #define dh_callflag_i32 0
#define dh_callflag_s32 0 #define dh_callflag_s32 0
@ -126,8 +108,7 @@
#define dh_callflag_noreturn TCG_CALL_NO_RETURN #define dh_callflag_noreturn TCG_CALL_NO_RETURN
#define dh_callflag(t) glue(dh_callflag_, dh_alias(t)) #define dh_callflag(t) glue(dh_callflag_, dh_alias(t))
#define dh_sizemask(t, n) \ #define dh_typemask(t, n) (dh_typecode(t) << (n * 3))
((dh_is_64bit(t) << (n*2)) | (dh_is_signed(t) << (n*2+1)))
#define dh_arg(t, n) \ #define dh_arg(t, n) \
glue(glue(tcgv_, dh_alias(t)), _temp)(glue(arg, n)) glue(glue(tcgv_, dh_alias(t)), _temp)(glue(arg, n))

View File

@ -13,50 +13,50 @@
#define DEF_HELPER_FLAGS_0(NAME, FLAGS, ret) \ #define DEF_HELPER_FLAGS_0(NAME, FLAGS, ret) \
{ .func = HELPER(NAME), .name = str(NAME), \ { .func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(ret), \ .flags = FLAGS | dh_callflag(ret), \
.sizemask = dh_sizemask(ret, 0) }, .typemask = dh_typemask(ret, 0) },
#define DEF_HELPER_FLAGS_1(NAME, FLAGS, ret, t1) \ #define DEF_HELPER_FLAGS_1(NAME, FLAGS, ret, t1) \
{ .func = HELPER(NAME), .name = str(NAME), \ { .func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(ret), \ .flags = FLAGS | dh_callflag(ret), \
.sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) }, .typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) },
#define DEF_HELPER_FLAGS_2(NAME, FLAGS, ret, t1, t2) \ #define DEF_HELPER_FLAGS_2(NAME, FLAGS, ret, t1, t2) \
{ .func = HELPER(NAME), .name = str(NAME), \ { .func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(ret), \ .flags = FLAGS | dh_callflag(ret), \
.sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) \ .typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
| dh_sizemask(t2, 2) }, | dh_typemask(t2, 2) },
#define DEF_HELPER_FLAGS_3(NAME, FLAGS, ret, t1, t2, t3) \ #define DEF_HELPER_FLAGS_3(NAME, FLAGS, ret, t1, t2, t3) \
{ .func = HELPER(NAME), .name = str(NAME), \ { .func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(ret), \ .flags = FLAGS | dh_callflag(ret), \
.sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) \ .typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
| dh_sizemask(t2, 2) | dh_sizemask(t3, 3) }, | dh_typemask(t2, 2) | dh_typemask(t3, 3) },
#define DEF_HELPER_FLAGS_4(NAME, FLAGS, ret, t1, t2, t3, t4) \ #define DEF_HELPER_FLAGS_4(NAME, FLAGS, ret, t1, t2, t3, t4) \
{ .func = HELPER(NAME), .name = str(NAME), \ { .func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(ret), \ .flags = FLAGS | dh_callflag(ret), \
.sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) \ .typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
| dh_sizemask(t2, 2) | dh_sizemask(t3, 3) | dh_sizemask(t4, 4) }, | dh_typemask(t2, 2) | dh_typemask(t3, 3) | dh_typemask(t4, 4) },
#define DEF_HELPER_FLAGS_5(NAME, FLAGS, ret, t1, t2, t3, t4, t5) \ #define DEF_HELPER_FLAGS_5(NAME, FLAGS, ret, t1, t2, t3, t4, t5) \
{ .func = HELPER(NAME), .name = str(NAME), \ { .func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(ret), \ .flags = FLAGS | dh_callflag(ret), \
.sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) \ .typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
| dh_sizemask(t2, 2) | dh_sizemask(t3, 3) | dh_sizemask(t4, 4) \ | dh_typemask(t2, 2) | dh_typemask(t3, 3) | dh_typemask(t4, 4) \
| dh_sizemask(t5, 5) }, | dh_typemask(t5, 5) },
#define DEF_HELPER_FLAGS_6(NAME, FLAGS, ret, t1, t2, t3, t4, t5, t6) \ #define DEF_HELPER_FLAGS_6(NAME, FLAGS, ret, t1, t2, t3, t4, t5, t6) \
{ .func = HELPER(NAME), .name = str(NAME), \ { .func = HELPER(NAME), .name = str(NAME), \
.flags = FLAGS | dh_callflag(ret), \ .flags = FLAGS | dh_callflag(ret), \
.sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) \ .typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
| dh_sizemask(t2, 2) | dh_sizemask(t3, 3) | dh_sizemask(t4, 4) \ | dh_typemask(t2, 2) | dh_typemask(t3, 3) | dh_typemask(t4, 4) \
| dh_sizemask(t5, 5) | dh_sizemask(t6, 6) }, | dh_typemask(t5, 5) | dh_typemask(t6, 6) },
#define DEF_HELPER_FLAGS_7(NAME, FLAGS, ret, t1, t2, t3, t4, t5, t6, t7) \ #define DEF_HELPER_FLAGS_7(NAME, FLAGS, ret, t1, t2, t3, t4, t5, t6, t7) \
{ .func = HELPER(NAME), .name = str(NAME), .flags = FLAGS, \ { .func = HELPER(NAME), .name = str(NAME), .flags = FLAGS, \
.sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) \ .typemask = dh_typemask(ret, 0) | dh_typemask(t1, 1) \
| dh_sizemask(t2, 2) | dh_sizemask(t3, 3) | dh_sizemask(t4, 4) \ | dh_typemask(t2, 2) | dh_typemask(t3, 3) | dh_typemask(t4, 4) \
| dh_sizemask(t5, 5) | dh_sizemask(t6, 6) | dh_sizemask(t7, 7) }, | dh_typemask(t5, 5) | dh_typemask(t6, 6) | dh_typemask(t7, 7) },
#include "helper.h" #include "helper.h"
#include "trace/generated-helpers.h" #include "trace/generated-helpers.h"

View File

@ -1,12 +1,9 @@
#if TARGET_REGISTER_BITS == 64 #if TARGET_REGISTER_BITS == 64
# define dh_alias_tr i64 # define dh_alias_tr i64
# define dh_is_64bit_tr 1
#else #else
# define dh_alias_tr i32 # define dh_alias_tr i32
# define dh_is_64bit_tr 0
#endif #endif
#define dh_ctype_tr target_ureg #define dh_ctype_tr target_ureg
#define dh_is_signed_tr 0
DEF_HELPER_2(excp, noreturn, env, int) DEF_HELPER_2(excp, noreturn, env, int)
DEF_HELPER_FLAGS_2(tsv, TCG_CALL_NO_WG, void, env, tr) DEF_HELPER_FLAGS_2(tsv, TCG_CALL_NO_WG, void, env, tr)

View File

@ -30,9 +30,6 @@
#define dh_ctype_Reg Reg * #define dh_ctype_Reg Reg *
#define dh_ctype_ZMMReg ZMMReg * #define dh_ctype_ZMMReg ZMMReg *
#define dh_ctype_MMXReg MMXReg * #define dh_ctype_MMXReg MMXReg *
#define dh_is_signed_Reg dh_is_signed_ptr
#define dh_is_signed_ZMMReg dh_is_signed_ptr
#define dh_is_signed_MMXReg dh_is_signed_ptr
DEF_HELPER_3(glue(psrlw, SUFFIX), void, env, Reg, Reg) DEF_HELPER_3(glue(psrlw, SUFFIX), void, env, Reg, Reg)
DEF_HELPER_3(glue(psraw, SUFFIX), void, env, Reg, Reg) DEF_HELPER_3(glue(psraw, SUFFIX), void, env, Reg, Reg)

View File

@ -17,7 +17,6 @@ DEF_HELPER_4(cas2l_parallel, void, env, i32, i32, i32)
#define dh_alias_fp ptr #define dh_alias_fp ptr
#define dh_ctype_fp FPReg * #define dh_ctype_fp FPReg *
#define dh_is_signed_fp dh_is_signed_ptr
DEF_HELPER_3(exts32, void, env, fp, s32) DEF_HELPER_3(exts32, void, env, fp, s32)
DEF_HELPER_3(extf32, void, env, fp, f32) DEF_HELPER_3(extf32, void, env, fp, f32)

View File

@ -109,11 +109,9 @@ DEF_HELPER_FLAGS_1(ftsqrt, TCG_CALL_NO_RWG_SE, i32, i64)
#define dh_alias_avr ptr #define dh_alias_avr ptr
#define dh_ctype_avr ppc_avr_t * #define dh_ctype_avr ppc_avr_t *
#define dh_is_signed_avr dh_is_signed_ptr
#define dh_alias_vsr ptr #define dh_alias_vsr ptr
#define dh_ctype_vsr ppc_vsr_t * #define dh_ctype_vsr ppc_vsr_t *
#define dh_is_signed_vsr dh_is_signed_ptr
DEF_HELPER_3(vavgub, void, avr, avr, avr) DEF_HELPER_3(vavgub, void, avr, avr, avr)
DEF_HELPER_3(vavguh, void, avr, avr, avr) DEF_HELPER_3(vavguh, void, avr, avr, avr)
@ -697,7 +695,6 @@ DEF_HELPER_3(store_601_batu, void, env, i32, tl)
#define dh_alias_fprp ptr #define dh_alias_fprp ptr
#define dh_ctype_fprp ppc_fprp_t * #define dh_ctype_fprp ppc_fprp_t *
#define dh_is_signed_fprp dh_is_signed_ptr
DEF_HELPER_4(dadd, void, env, fprp, fprp, fprp) DEF_HELPER_4(dadd, void, env, fprp, fprp, fprp)
DEF_HELPER_4(daddq, void, env, fprp, fprp, fprp) DEF_HELPER_4(daddq, void, env, fprp, fprp, fprp)

View File

@ -536,7 +536,7 @@ typedef struct TCGHelperInfo {
void *func; void *func;
const char *name; const char *name;
unsigned flags; unsigned flags;
unsigned sizemask; unsigned typemask;
} TCGHelperInfo; } TCGHelperInfo;
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
@ -1395,13 +1395,13 @@ bool tcg_op_supported(TCGOpcode op)
void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args) void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
{ {
int i, real_args, nb_rets, pi; int i, real_args, nb_rets, pi;
unsigned sizemask, flags; unsigned typemask, flags;
TCGHelperInfo *info; TCGHelperInfo *info;
TCGOp *op; TCGOp *op;
info = g_hash_table_lookup(helper_table, (gpointer)func); info = g_hash_table_lookup(helper_table, (gpointer)func);
flags = info->flags; flags = info->flags;
sizemask = info->sizemask; typemask = info->typemask;
#ifdef CONFIG_PLUGIN #ifdef CONFIG_PLUGIN
/* detect non-plugin helpers */ /* detect non-plugin helpers */
@ -1414,36 +1414,41 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
&& !defined(CONFIG_TCG_INTERPRETER) && !defined(CONFIG_TCG_INTERPRETER)
/* We have 64-bit values in one register, but need to pass as two /* We have 64-bit values in one register, but need to pass as two
separate parameters. Split them. */ separate parameters. Split them. */
int orig_sizemask = sizemask; int orig_typemask = typemask;
int orig_nargs = nargs; int orig_nargs = nargs;
TCGv_i64 retl, reth; TCGv_i64 retl, reth;
TCGTemp *split_args[MAX_OPC_PARAM]; TCGTemp *split_args[MAX_OPC_PARAM];
retl = NULL; retl = NULL;
reth = NULL; reth = NULL;
if (sizemask != 0) { typemask = 0;
for (i = real_args = 0; i < nargs; ++i) { for (i = real_args = 0; i < nargs; ++i) {
int is_64bit = sizemask & (1 << (i+1)*2); int argtype = extract32(orig_typemask, (i + 1) * 3, 3);
if (is_64bit) { bool is_64bit = (argtype & ~1) == dh_typecode_i64;
TCGv_i64 orig = temp_tcgv_i64(args[i]);
TCGv_i32 h = tcg_temp_new_i32(); if (is_64bit) {
TCGv_i32 l = tcg_temp_new_i32(); TCGv_i64 orig = temp_tcgv_i64(args[i]);
tcg_gen_extr_i64_i32(l, h, orig); TCGv_i32 h = tcg_temp_new_i32();
split_args[real_args++] = tcgv_i32_temp(h); TCGv_i32 l = tcg_temp_new_i32();
split_args[real_args++] = tcgv_i32_temp(l); tcg_gen_extr_i64_i32(l, h, orig);
} else { split_args[real_args++] = tcgv_i32_temp(h);
split_args[real_args++] = args[i]; typemask |= dh_typecode_i32 << (real_args * 3);
} split_args[real_args++] = tcgv_i32_temp(l);
typemask |= dh_typecode_i32 << (real_args * 3);
} else {
split_args[real_args++] = args[i];
typemask |= argtype << (real_args * 3);
} }
nargs = real_args;
args = split_args;
sizemask = 0;
} }
nargs = real_args;
args = split_args;
#elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64 #elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
for (i = 0; i < nargs; ++i) { for (i = 0; i < nargs; ++i) {
int is_64bit = sizemask & (1 << (i+1)*2); int argtype = extract32(typemask, (i + 1) * 3, 3);
int is_signed = sizemask & (2 << (i+1)*2); bool is_32bit = (argtype & ~1) == dh_typecode_i32;
if (!is_64bit) { bool is_signed = argtype & 1;
if (is_32bit) {
TCGv_i64 temp = tcg_temp_new_i64(); TCGv_i64 temp = tcg_temp_new_i64();
TCGv_i64 orig = temp_tcgv_i64(args[i]); TCGv_i64 orig = temp_tcgv_i64(args[i]);
if (is_signed) { if (is_signed) {
@ -1462,7 +1467,7 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
if (ret != NULL) { if (ret != NULL) {
#if defined(__sparc__) && !defined(__arch64__) \ #if defined(__sparc__) && !defined(__arch64__) \
&& !defined(CONFIG_TCG_INTERPRETER) && !defined(CONFIG_TCG_INTERPRETER)
if (orig_sizemask & 1) { if ((typemask & 6) == dh_typecode_i64) {
/* The 32-bit ABI is going to return the 64-bit value in /* The 32-bit ABI is going to return the 64-bit value in
the %o0/%o1 register pair. Prepare for this by using the %o0/%o1 register pair. Prepare for this by using
two return temporaries, and reassemble below. */ two return temporaries, and reassemble below. */
@ -1476,7 +1481,7 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
nb_rets = 1; nb_rets = 1;
} }
#else #else
if (TCG_TARGET_REG_BITS < 64 && (sizemask & 1)) { if (TCG_TARGET_REG_BITS < 64 && (typemask & 6) == dh_typecode_i64) {
#ifdef HOST_WORDS_BIGENDIAN #ifdef HOST_WORDS_BIGENDIAN
op->args[pi++] = temp_arg(ret + 1); op->args[pi++] = temp_arg(ret + 1);
op->args[pi++] = temp_arg(ret); op->args[pi++] = temp_arg(ret);
@ -1497,7 +1502,9 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
real_args = 0; real_args = 0;
for (i = 0; i < nargs; i++) { for (i = 0; i < nargs; i++) {
int is_64bit = sizemask & (1 << (i+1)*2); int argtype = extract32(typemask, (i + 1) * 3, 3);
bool is_64bit = (argtype & ~1) == dh_typecode_i64;
if (TCG_TARGET_REG_BITS < 64 && is_64bit) { if (TCG_TARGET_REG_BITS < 64 && is_64bit) {
#ifdef TCG_TARGET_CALL_ALIGN_ARGS #ifdef TCG_TARGET_CALL_ALIGN_ARGS
/* some targets want aligned 64 bit args */ /* some targets want aligned 64 bit args */
@ -1542,7 +1549,9 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
&& !defined(CONFIG_TCG_INTERPRETER) && !defined(CONFIG_TCG_INTERPRETER)
/* Free all of the parts we allocated above. */ /* Free all of the parts we allocated above. */
for (i = real_args = 0; i < orig_nargs; ++i) { for (i = real_args = 0; i < orig_nargs; ++i) {
int is_64bit = orig_sizemask & (1 << (i+1)*2); int argtype = extract32(orig_typemask, (i + 1) * 3, 3);
bool is_64bit = (argtype & ~1) == dh_typecode_i64;
if (is_64bit) { if (is_64bit) {
tcg_temp_free_internal(args[real_args++]); tcg_temp_free_internal(args[real_args++]);
tcg_temp_free_internal(args[real_args++]); tcg_temp_free_internal(args[real_args++]);
@ -1550,7 +1559,7 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
real_args++; real_args++;
} }
} }
if (orig_sizemask & 1) { if ((orig_typemask & 6) == dh_typecode_i64) {
/* The 32-bit ABI returned two 32-bit pieces. Re-assemble them. /* The 32-bit ABI returned two 32-bit pieces. Re-assemble them.
Note that describing these as TCGv_i64 eliminates an unnecessary Note that describing these as TCGv_i64 eliminates an unnecessary
zero-extension that tcg_gen_concat_i32_i64 would create. */ zero-extension that tcg_gen_concat_i32_i64 would create. */
@ -1560,8 +1569,10 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
} }
#elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64 #elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
for (i = 0; i < nargs; ++i) { for (i = 0; i < nargs; ++i) {
int is_64bit = sizemask & (1 << (i+1)*2); int argtype = extract32(typemask, (i + 1) * 3, 3);
if (!is_64bit) { bool is_32bit = (argtype & ~1) == dh_typecode_i32;
if (is_32bit) {
tcg_temp_free_internal(args[i]); tcg_temp_free_internal(args[i]);
} }
} }