diff options
author | jules <jules@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-08-01 12:34:15 +0000 |
---|---|---|
committer | jules <jules@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-08-01 12:34:15 +0000 |
commit | 37cd19a47e20d77986b5e2d65cbba5ca79794730 (patch) | |
tree | 891354cf2cb68748e3ddbae9a66feb3fffe87e98 /gcc/calls.c | |
parent | 928c11f3f3955eb7f678dacf029346164e568c4d (diff) | |
download | gcc-37cd19a47e20d77986b5e2d65cbba5ca79794730.tar.gz |
gcc/
* calls.c (emit_library_call_value_1): Support padding for libcall
arguments and return values.
* config/arm/arm.c (arm_pad_arg_upward): Pad half-float values
downwards in big-endian mode.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@177022 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/calls.c')
-rw-r--r-- | gcc/calls.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/gcc/calls.c b/gcc/calls.c index dfa9ceb5563..7ad30b4245c 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -3829,13 +3829,41 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value, rtx val = argvec[argnum].value; rtx reg = argvec[argnum].reg; int partial = argvec[argnum].partial; - + int size = 0; + /* Handle calls that pass values in multiple non-contiguous locations. The PA64 has examples of this for library calls. */ if (reg != 0 && GET_CODE (reg) == PARALLEL) emit_group_load (reg, val, NULL_TREE, GET_MODE_SIZE (mode)); else if (reg != 0 && partial == 0) - emit_move_insn (reg, val); + { + emit_move_insn (reg, val); +#ifdef BLOCK_REG_PADDING + size = GET_MODE_SIZE (argvec[argnum].mode); + + /* Copied from load_register_parameters. */ + + /* Handle case where we have a value that needs shifting + up to the msb. eg. a QImode value and we're padding + upward on a BYTES_BIG_ENDIAN machine. */ + if (size < UNITS_PER_WORD + && (argvec[argnum].locate.where_pad + == (BYTES_BIG_ENDIAN ? upward : downward))) + { + rtx x; + int shift = (UNITS_PER_WORD - size) * BITS_PER_UNIT; + + /* Assigning REG here rather than a temp makes CALL_FUSAGE + report the whole reg as used. Strictly speaking, the + call only uses SIZE bytes at the msb end, but it doesn't + seem worth generating rtl to say that. */ + reg = gen_rtx_REG (word_mode, REGNO (reg)); + x = expand_shift (LSHIFT_EXPR, word_mode, reg, shift, reg, 1); + if (x != reg) + emit_move_insn (reg, x); + } +#endif + } NO_DEFER_POP; } @@ -3901,6 +3929,15 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value, valreg, old_inhibit_defer_pop + 1, call_fusage, flags, args_so_far); + /* Right-shift returned value if necessary. */ + if (!pcc_struct_value + && TYPE_MODE (tfom) != BLKmode + && targetm.calls.return_in_msb (tfom)) + { + shift_return_value (TYPE_MODE (tfom), false, valreg); + valreg = gen_rtx_REG (TYPE_MODE (tfom), REGNO (valreg)); + } + /* For calls to `setjmp', etc., inform function.c:setjmp_warnings that it should complain if nonvolatile values are live. For functions that cannot return, inform flow that control does not |