mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 18:23:57 -06:00
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:
parent
3ccf6cd0e3
commit
7319d83a73
7 changed files with 67 additions and 85 deletions
71
tcg/tcg.c
71
tcg/tcg.c
|
@ -536,7 +536,7 @@ typedef struct TCGHelperInfo {
|
|||
void *func;
|
||||
const char *name;
|
||||
unsigned flags;
|
||||
unsigned sizemask;
|
||||
unsigned typemask;
|
||||
} TCGHelperInfo;
|
||||
|
||||
#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)
|
||||
{
|
||||
int i, real_args, nb_rets, pi;
|
||||
unsigned sizemask, flags;
|
||||
unsigned typemask, flags;
|
||||
TCGHelperInfo *info;
|
||||
TCGOp *op;
|
||||
|
||||
info = g_hash_table_lookup(helper_table, (gpointer)func);
|
||||
flags = info->flags;
|
||||
sizemask = info->sizemask;
|
||||
typemask = info->typemask;
|
||||
|
||||
#ifdef CONFIG_PLUGIN
|
||||
/* detect non-plugin helpers */
|
||||
|
@ -1414,36 +1414,41 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
|
|||
&& !defined(CONFIG_TCG_INTERPRETER)
|
||||
/* We have 64-bit values in one register, but need to pass as two
|
||||
separate parameters. Split them. */
|
||||
int orig_sizemask = sizemask;
|
||||
int orig_typemask = typemask;
|
||||
int orig_nargs = nargs;
|
||||
TCGv_i64 retl, reth;
|
||||
TCGTemp *split_args[MAX_OPC_PARAM];
|
||||
|
||||
retl = NULL;
|
||||
reth = NULL;
|
||||
if (sizemask != 0) {
|
||||
for (i = real_args = 0; i < nargs; ++i) {
|
||||
int is_64bit = sizemask & (1 << (i+1)*2);
|
||||
if (is_64bit) {
|
||||
TCGv_i64 orig = temp_tcgv_i64(args[i]);
|
||||
TCGv_i32 h = tcg_temp_new_i32();
|
||||
TCGv_i32 l = tcg_temp_new_i32();
|
||||
tcg_gen_extr_i64_i32(l, h, orig);
|
||||
split_args[real_args++] = tcgv_i32_temp(h);
|
||||
split_args[real_args++] = tcgv_i32_temp(l);
|
||||
} else {
|
||||
split_args[real_args++] = args[i];
|
||||
}
|
||||
typemask = 0;
|
||||
for (i = real_args = 0; i < nargs; ++i) {
|
||||
int argtype = extract32(orig_typemask, (i + 1) * 3, 3);
|
||||
bool is_64bit = (argtype & ~1) == dh_typecode_i64;
|
||||
|
||||
if (is_64bit) {
|
||||
TCGv_i64 orig = temp_tcgv_i64(args[i]);
|
||||
TCGv_i32 h = tcg_temp_new_i32();
|
||||
TCGv_i32 l = tcg_temp_new_i32();
|
||||
tcg_gen_extr_i64_i32(l, h, orig);
|
||||
split_args[real_args++] = tcgv_i32_temp(h);
|
||||
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
|
||||
for (i = 0; i < nargs; ++i) {
|
||||
int is_64bit = sizemask & (1 << (i+1)*2);
|
||||
int is_signed = sizemask & (2 << (i+1)*2);
|
||||
if (!is_64bit) {
|
||||
int argtype = extract32(typemask, (i + 1) * 3, 3);
|
||||
bool is_32bit = (argtype & ~1) == dh_typecode_i32;
|
||||
bool is_signed = argtype & 1;
|
||||
|
||||
if (is_32bit) {
|
||||
TCGv_i64 temp = tcg_temp_new_i64();
|
||||
TCGv_i64 orig = temp_tcgv_i64(args[i]);
|
||||
if (is_signed) {
|
||||
|
@ -1462,7 +1467,7 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
|
|||
if (ret != NULL) {
|
||||
#if defined(__sparc__) && !defined(__arch64__) \
|
||||
&& !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 %o0/%o1 register pair. Prepare for this by using
|
||||
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;
|
||||
}
|
||||
#else
|
||||
if (TCG_TARGET_REG_BITS < 64 && (sizemask & 1)) {
|
||||
if (TCG_TARGET_REG_BITS < 64 && (typemask & 6) == dh_typecode_i64) {
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
op->args[pi++] = temp_arg(ret + 1);
|
||||
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;
|
||||
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) {
|
||||
#ifdef TCG_TARGET_CALL_ALIGN_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)
|
||||
/* Free all of the parts we allocated above. */
|
||||
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) {
|
||||
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++;
|
||||
}
|
||||
}
|
||||
if (orig_sizemask & 1) {
|
||||
if ((orig_typemask & 6) == dh_typecode_i64) {
|
||||
/* The 32-bit ABI returned two 32-bit pieces. Re-assemble them.
|
||||
Note that describing these as TCGv_i64 eliminates an unnecessary
|
||||
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
|
||||
for (i = 0; i < nargs; ++i) {
|
||||
int is_64bit = sizemask & (1 << (i+1)*2);
|
||||
if (!is_64bit) {
|
||||
int argtype = extract32(typemask, (i + 1) * 3, 3);
|
||||
bool is_32bit = (argtype & ~1) == dh_typecode_i32;
|
||||
|
||||
if (is_32bit) {
|
||||
tcg_temp_free_internal(args[i]);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue