mirror of https://github.com/proxmox/mirror_qemu
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
parent
eb8b0224fc
commit
e2a9dd6b6b
70
tcg/tcg.c
70
tcg/tcg.c
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue