Hi, all, There is a problem in nds32.h to determine available register number for passing BLKmode argument. The original checking only refers to NDS32_NEED_N_REGS_FOR_ARG macro but that is not sufficient to make decision of using odd or even register number. It is supposed to further check the type alignment.
We define a new macro NDS32_MODE_TYPE_ALIGN and rewrite NDS32_AVAILABLE_REGNUM_FOR_ARG definition. The patch for nds32.c and nds32.h is as follow: Index: gcc/config/nds32/nds32.h =================================================================== --- gcc/config/nds32/nds32.h (revision 206139) +++ gcc/config/nds32/nds32.h (working copy) @@ -126,6 +126,11 @@ #define NDS32_SINGLE_WORD_ALIGN_P(value) (((value) & 0x03) == 0) #define NDS32_DOUBLE_WORD_ALIGN_P(value) (((value) & 0x07) == 0) +/* Get alignment according to mode or type information. + When 'type' is nonnull, there is no need to look at 'mode'. */ +#define NDS32_MODE_TYPE_ALIGN(mode, type) \ + (type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode)) + /* Round X up to the nearest double word. */ #define NDS32_ROUND_UP_DOUBLE_WORD(value) (((value) + 7) & ~7) @@ -142,12 +147,18 @@ /* This macro is used to return the register number for passing argument. We need to obey the following rules: 1. If it is required MORE THAN one register, - make sure the register number is a even value. + we need to further check if it really needs to be + aligned on double words. + a) If double word alignment is necessary, + the register number must be even value. + b) Otherwise, the register number can be odd or even value. 2. If it is required ONLY one register, the register number can be odd or even value. */ -#define NDS32_AVAILABLE_REGNUM_FOR_ARG(reg_offset, mode, type) \ - ((NDS32_NEED_N_REGS_FOR_ARG (mode, type) > 1) \ - ? (((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM + 1) & ~1) \ +#define NDS32_AVAILABLE_REGNUM_FOR_ARG(reg_offset, mode, type) \ + ((NDS32_NEED_N_REGS_FOR_ARG (mode, type) > 1) \ + ? ((NDS32_MODE_TYPE_ALIGN (mode, type) > PARM_BOUNDARY) \ + ? (((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM + 1) & ~1) \ + : ((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM)) \ : ((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM)) /* This macro is to check if there are still available registers Index: gcc/config/nds32/nds32.c =================================================================== --- gcc/config/nds32/nds32.c (revision 206139) +++ gcc/config/nds32/nds32.c (working copy) @@ -1438,8 +1438,8 @@ { unsigned int align; - /* When 'type' is nonnull, there is no need to look at 'mode'. */ - align = (type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode)); + /* Pick up the alignment according to the mode or type. */ + align = NDS32_MODE_TYPE_ALIGN (mode, type); return (align > PARM_BOUNDARY); } @@ -1853,10 +1853,10 @@ if (NDS32_ARG_PASS_IN_REG_P (cum->reg_offset, mode, type)) { /* Pick up the next available register number. */ - return gen_rtx_REG (mode, - NDS32_AVAILABLE_REGNUM_FOR_ARG (cum->reg_offset, - mode, - type)); + unsigned int regno; + + regno = NDS32_AVAILABLE_REGNUM_FOR_ARG (cum->reg_offset, mode, type); + return gen_rtx_REG (mode, regno); } else { And the gcc/ChangeLog is as below: +2013-12-20 Chung-Ju Wu <jasonw...@gmail.com> + + * config/nds32/nds32.h (NDS32_MODE_TYPE_ALIGN): New macro. + (NDS32_AVAILABLE_REGNUM_FOR_ARG): Use more accurate alignment checking + to determine available register number. + * config/nds32/nds32.c (nds32_needs_double_word_align): Use new + macro NDS32_MODE_TYPE_ALIGN. + (nds32_function_arg): Refine code layout. + 2013-12-19 Jeff Law <l...@redhat.com> * doc/invoke.texi: (dump-rtl-ree): Fix typo and clarify ree Bootstrapped and tested on nds32le-elf/nds32be-elf target. Committed as Rev.206142: http://gcc.gnu.org/r206142 Best regards, jasonwucj