diff options
author | Richard Henderson <rth@twiddle.net> | 2010-06-14 17:35:27 -0700 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2010-06-16 11:29:11 +0200 |
commit | 2bece2c88331f024a46527634e3dd91c71d22141 (patch) | |
tree | 2275cb777821df8aa66ea092bae2124b9923d01b /tcg/tcg.c | |
parent | d2c5efd89fe319f150aba0b67e394f23f6c07ba6 (diff) |
tcg: Optionally sign-extend 32-bit arguments for 64-bit hosts.
Some hosts (amd64, ia64) have an ABI that ignores the high bits
of the 64-bit register when passing 32-bit arguments. Others
require the value to be properly sign-extended for the type.
I.e. "int32_t" must be sign-extended and "uint32_t" must be
zero-extended to 64-bits.
To effect this, extend the "sizemask" parameter to tcg_gen_callN
to include the signedness of the type of each parameter. If the
tcg target requires it, extend each 32-bit argument into a 64-bit
temp and pass that to the function call.
This ABI feature is required by sparc64, ppc64 and s390x.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'tcg/tcg.c')
-rw-r--r-- | tcg/tcg.c | 41 |
1 files changed, 35 insertions, 6 deletions
@@ -560,6 +560,24 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags, int real_args; int nb_rets; TCGArg *nparam; + +#if 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) { + TCGv_i64 temp = tcg_temp_new_i64(); + TCGv_i64 orig = MAKE_TCGV_I64(args[i]); + if (is_signed) { + tcg_gen_ext32s_i64(temp, orig); + } else { + tcg_gen_ext32u_i64(temp, orig); + } + args[i] = GET_TCGV_I64(temp); + } + } +#endif /* TCG_TARGET_EXTEND_ARGS */ + *gen_opc_ptr++ = INDEX_op_call; nparam = gen_opparam_ptr++; #ifdef TCG_TARGET_I386 @@ -588,7 +606,8 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags, real_args = 0; for (i = 0; i < nargs; i++) { #if TCG_TARGET_REG_BITS < 64 - if (sizemask & (2 << i)) { + int is_64bit = sizemask & (1 << (i+1)*2); + if (is_64bit) { #ifdef TCG_TARGET_I386 /* REGPARM case: if the third parameter is 64 bit, it is allocated on the stack */ @@ -622,12 +641,12 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags, *gen_opparam_ptr++ = args[i] + 1; #endif real_args += 2; - } else -#endif - { - *gen_opparam_ptr++ = args[i]; - real_args++; + continue; } +#endif /* TCG_TARGET_REG_BITS < 64 */ + + *gen_opparam_ptr++ = args[i]; + real_args++; } *gen_opparam_ptr++ = GET_TCGV_PTR(func); @@ -637,6 +656,16 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags, /* total parameters, needed to go backward in the instruction stream */ *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3; + +#if 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) { + TCGv_i64 temp = MAKE_TCGV_I64(args[i]); + tcg_temp_free_i64(temp); + } + } +#endif /* TCG_TARGET_EXTEND_ARGS */ } #if TCG_TARGET_REG_BITS == 32 |