This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

ppc64 assembler issue


Cort brought to my attention the fact that when generating for ppc64,
gcc generates output that gas doesn't like.  It stems around the 
definition of "lis".

There is some compatibility code in the assembler to allow the
argument to "lis" (and three others) to be signed or unsigned if
and only if we are generating 32-bit code.  In 64-bit mode it
forces the values to be signed.  Assuming that "lis" et al do 
in fact sign extend the value in the 64-bit register, this 
seems to me a perfectly reasonable thing for gas to bitch about.

I'm actually curious about that last point, since that's kind of in
line with some of the comments in GCC, but not the code.  The 'J'
constraint implemented an unsigned field, as does the code in
num_insns_constant_wide.

Anyway, I think the following will do what's needed.  Except for the
num_insns_constant_wide thing, which I just noticed. 

Care to test it out, Cort?


r~

	* rs6000.c (print_operand) [v]: Always sign extend the value.
	(rs6000_allocate_stack_space): Don't zero extend the operands to lis.
	* rs6000.h (CONST_OK_FOR_LETTER_P): 'J' checks for a signed field.
	Fix typo for 'P'.

Index: rs6000.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.67
diff -c -p -d -r1.67 rs6000.c
*** rs6000.c	1999/04/30 15:06:23	1.67
--- rs6000.c	1999/05/08 08:08:57
*************** print_operand (file, x, code)
*** 3067,3082 ****
        if (! INT_P (x))
  	output_operand_lossage ("invalid %%v value");
  
!       {
! 	int value = (INT_LOWPART (x) >> 16) & 0xffff;
! 
! 	/* Solaris assembler doesn't like lis 0,0x80000 */
! 	if (DEFAULT_ABI == ABI_SOLARIS && (value & 0x8000) != 0)
! 	  fprintf (file, "%d", value | (~0 << 16));
! 	else
! 	  fprintf (file, "0x%x", value);
! 	return;
!       }
  
      case 'U':
        /* Print `u' if this has an auto-increment or auto-decrement.  */
--- 3067,3075 ----
        if (! INT_P (x))
  	output_operand_lossage ("invalid %%v value");
  
!       fprintf (file, "%d",
! 	       (((INT_LOWPART (x) >> 16) & 0xffff) ^ 0x8000) - 0x8000;
!       return;
  
      case 'U':
        /* Print `u' if this has an auto-increment or auto-decrement.  */
*************** print_operand (file, x, code)
*** 3129,3136 ****
        /* If constant, low-order 16 bits of constant, signed.  Otherwise, write
  	 normally.  */
        if (INT_P (x))
! 	fprintf (file, "%d",
! 		 (INT_LOWPART (x) & 0xffff) - 2 * (INT_LOWPART (x) & 0x8000));
        else
  	print_operand (file, x, 0);
        return;
--- 3122,3128 ----
        /* If constant, low-order 16 bits of constant, signed.  Otherwise, write
  	 normally.  */
        if (INT_P (x))
! 	fprintf (file, "%d", ((INT_LOWPART (x) & 0xffff) ^ 0x8000) - 0x8000);
        else
  	print_operand (file, x, 0);
        return;
*************** rs6000_allocate_stack_space (file, size,
*** 3967,3973 ****
  	    fprintf (file, "\tmr %s,%s\n", reg_names[12], reg_names[1]);
  
  	  asm_fprintf (file, "\t{liu|lis} %s,%d\n\t{oril|ori} %s,%s,%d\n",
! 		       reg_names[0], (neg_size >> 16) & 0xffff,
  		       reg_names[0], reg_names[0], neg_size & 0xffff);
  	  asm_fprintf (file,
  		       (TARGET_32BIT) ? "\t{stux|stwux} %s,%s,%s\n" : "\tstdux %s,%s,%s\n",
--- 3959,3965 ----
  	    fprintf (file, "\tmr %s,%s\n", reg_names[12], reg_names[1]);
  
  	  asm_fprintf (file, "\t{liu|lis} %s,%d\n\t{oril|ori} %s,%s,%d\n",
! 		       reg_names[0], neg_size >> 16,
  		       reg_names[0], reg_names[0], neg_size & 0xffff);
  	  asm_fprintf (file,
  		       (TARGET_32BIT) ? "\t{stux|stwux} %s,%s,%s\n" : "\tstdux %s,%s,%s\n",
*************** rs6000_allocate_stack_space (file, size,
*** 3983,3989 ****
        else
  	{
  	  asm_fprintf (file, "\t{liu|lis} %s,%d\n\t{oril|ori} %s,%s,%d\n",
! 		       reg_names[0], (neg_size >> 16) & 0xffff,
  		       reg_names[0], reg_names[0], neg_size & 0xffff);
  	  asm_fprintf (file, "\t{cax|add} %s,%s,%s\n", reg_names[1],
  		       reg_names[0], reg_names[1]);
--- 3975,3981 ----
        else
  	{
  	  asm_fprintf (file, "\t{liu|lis} %s,%d\n\t{oril|ori} %s,%s,%d\n",
! 		       reg_names[0], neg_size >> 16,
  		       reg_names[0], reg_names[0], neg_size & 0xffff);
  	  asm_fprintf (file, "\t{cax|add} %s,%s,%s\n", reg_names[1],
  		       reg_names[0], reg_names[1]);
*************** output_prolog (file, size)
*** 4219,4225 ****
  	      int neg_size = info->main_save_offset - info->total_size;
  	      loc = 0;
  	      asm_fprintf (file, "\t{liu|lis} %s,%d\n\t{oril|ori} %s,%s,%d\n",
! 			   reg_names[0], (neg_size >> 16) & 0xffff,
  			   reg_names[0], reg_names[0], neg_size & 0xffff);
  
  	      asm_fprintf (file, "\t{sf|subf} %s,%s,%s\n", reg_names[0], reg_names[0],
--- 4211,4217 ----
  	      int neg_size = info->main_save_offset - info->total_size;
  	      loc = 0;
  	      asm_fprintf (file, "\t{liu|lis} %s,%d\n\t{oril|ori} %s,%s,%d\n",
! 			   reg_names[0], neg_size >> 16,
  			   reg_names[0], reg_names[0], neg_size & 0xffff);
  
  	      asm_fprintf (file, "\t{sf|subf} %s,%s,%s\n", reg_names[0], reg_names[0],
Index: rs6000.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.46
diff -c -p -d -r1.46 rs6000.h
*** rs6000.h	1999/05/03 20:10:06	1.46
--- rs6000.h	1999/05/08 08:08:57
*************** enum reg_class
*** 1088,1094 ****
     Return 1 if VALUE is in the range specified by C.
  
     `I' is signed 16-bit constants
!    `J' is a constant with only the high-order 16 bits non-zero
     `K' is a constant with only the low-order 16 bits non-zero
     `L' is a constant that can be placed into a mask operand
     `M' is a constant that is greater than 31
--- 1088,1094 ----
     Return 1 if VALUE is in the range specified by C.
  
     `I' is signed 16-bit constants
!    `J' is a signed 16-bit constant shifted left 16 bits
     `K' is a constant with only the low-order 16 bits non-zero
     `L' is a constant that can be placed into a mask operand
     `M' is a constant that is greater than 31
*************** enum reg_class
*** 1098,1110 ****
  
  #define CONST_OK_FOR_LETTER_P(VALUE, C)					\
     ( (C) == 'I' ? (unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000	\
!    : (C) == 'J' ? ((VALUE) & (~ (HOST_WIDE_INT) 0xffff0000)) == 0	\
     : (C) == 'K' ? ((VALUE) & (~ (HOST_WIDE_INT) 0xffff)) == 0		\
     : (C) == 'L' ? mask_constant (VALUE)					\
     : (C) == 'M' ? (VALUE) > 31						\
     : (C) == 'N' ? exact_log2 (VALUE) >= 0				\
     : (C) == 'O' ? (VALUE) == 0						\
!    : (C) == 'P' ? (unsigned HOST_WIDE_INT) ((- (VALUE)) + 0x8000) < 0x1000 \
     : 0)
  
  /* Similar, but for floating constants, and defining letters G and H.
--- 1098,1111 ----
  
  #define CONST_OK_FOR_LETTER_P(VALUE, C)					\
     ( (C) == 'I' ? (unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000	\
!    : (C) == 'J' ? (((VALUE) & 0xffff) == 0				\
! 		   && ((VALUE) >> 31 == -1 || (VALUE) >> 31 == 0))	\
     : (C) == 'K' ? ((VALUE) & (~ (HOST_WIDE_INT) 0xffff)) == 0		\
     : (C) == 'L' ? mask_constant (VALUE)					\
     : (C) == 'M' ? (VALUE) > 31						\
     : (C) == 'N' ? exact_log2 (VALUE) >= 0				\
     : (C) == 'O' ? (VALUE) == 0						\
!    : (C) == 'P' ? (unsigned HOST_WIDE_INT) ((- (VALUE)) + 0x8000) < 0x10000 \
     : 0)
  
  /* Similar, but for floating constants, and defining letters G and H.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]