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

View file

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