tcg: Use TCG_CALL_ARG_EVEN for TCI special case

Change 32-bit tci TCG_TARGET_CALL_ARG_I32 to TCG_CALL_ARG_EVEN, to
force 32-bit values to be aligned to 64-bit.  With a small reorg
to the argument processing loop, this neatly replaces an ifdef for
CONFIG_TCG_INTERPRETER.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
master
Richard Henderson 2022-10-17 15:55:56 +10:00
parent eb8b0224fc
commit e2a9dd6b6b
2 changed files with 47 additions and 26 deletions

View File

@ -1533,36 +1533,56 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
real_args = 0;
for (i = 0; i < nargs; i++) {
int argtype = extract32(typemask, (i + 1) * 3, 3);
bool is_64bit = (argtype & ~1) == dh_typecode_i64;
bool want_align = false;
TCGCallArgumentKind kind;
TCGType type;
#if defined(CONFIG_TCG_INTERPRETER)
/*
* Align all arguments, so that they land in predictable places
* for passing off to ffi_call.
*/
want_align = true;
#else
/* Some targets want aligned 64 bit args */
if (is_64bit) {
want_align = TCG_TARGET_CALL_ARG_I64 == TCG_CALL_ARG_EVEN;
}
#endif
if (TCG_TARGET_REG_BITS < 64 && want_align && (real_args & 1)) {
op->args[pi++] = TCG_CALL_DUMMY_ARG;
real_args++;
switch (argtype) {
case dh_typecode_i32:
case dh_typecode_s32:
type = TCG_TYPE_I32;
break;
case dh_typecode_i64:
case dh_typecode_s64:
type = TCG_TYPE_I64;
break;
case dh_typecode_ptr:
type = TCG_TYPE_PTR;
break;
default:
g_assert_not_reached();
}
if (TCG_TARGET_REG_BITS < 64 && is_64bit) {
switch (type) {
case TCG_TYPE_I32:
kind = TCG_TARGET_CALL_ARG_I32;
break;
case TCG_TYPE_I64:
kind = TCG_TARGET_CALL_ARG_I64;
break;
default:
g_assert_not_reached();
}
switch (kind) {
case TCG_CALL_ARG_EVEN:
if (real_args & 1) {
op->args[pi++] = TCG_CALL_DUMMY_ARG;
real_args++;
}
/* fall through */
case TCG_CALL_ARG_NORMAL:
if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) {
op->args[pi++] = temp_arg(args[i]);
op->args[pi++] = temp_arg(args[i] + 1);
real_args += 2;
break;
}
op->args[pi++] = temp_arg(args[i]);
op->args[pi++] = temp_arg(args[i] + 1);
real_args += 2;
continue;
real_args++;
break;
default:
g_assert_not_reached();
}
op->args[pi++] = temp_arg(args[i]);
real_args++;
}
op->args[pi++] = (uintptr_t)func;
op->args[pi++] = (uintptr_t)info;

View File

@ -158,10 +158,11 @@ typedef enum {
/* Used for function call generation. */
#define TCG_TARGET_CALL_STACK_OFFSET 0
#define TCG_TARGET_STACK_ALIGN 8
#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL
#if TCG_TARGET_REG_BITS == 32
# define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_EVEN
# define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_EVEN
#else
# define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL
# define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL
#endif