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]

Function to compute size of i386 adress operand.


Hi
Many decisions in instruction selections depends on resulting opcode length
(because many CPUs hanle opcodes longer than 7 bytes badly). To make this
decision possible I've added function MEMORY_ADDRESS_SIZE to caluclate size
of memory operand.

Most of code is borrowed from print_operand function, so hope it works 
correctly. I've tested it in some cases.

It makes possible my NEG changes to work better.

Honza

Tue Apr 13 12:56:17 MET DST 1999 Jan Hubicka <hubicka@freesoft.cz>

	* i386.c (memory_address_size): New function.
	* i386.h: Declare it.

*** i386.c1	Tue Apr 13 11:41:24 1999
--- i386.c	Tue Apr 13 12:49:44 1999
*************** print_operand (file, x, code)
*** 3603,3608 ****
--- 3603,3751 ----
      }
  }
  
+ /* The function takes address rtx ADDR (not the whole MEM expression)
+    and return number of aditional bytes required to encode adress.  */
+ int
+ memory_address_size (addr)
+      rtx addr;
+ {
+   register rtx reg1, reg2, breg, ireg, offset;
+   debug_rtx (addr);
+   switch (GET_CODE (addr))
+     {
+       /* Register number is encoded in ModR/M array.  */
+     case REG:
+ 
+       /* ESI addressing makes instruction vector decoded on the K6.  We can
+          avoid this by ESI+0 addressing.  */
+ 
+       if ((REGNO_REG_CLASS (REGNO (addr)) == SIREG
+ 	   && ix86_cpu == PROCESSOR_K6 && !optimize_size)
+       /* EBP addresing mode can not be encoded directly.  */
+ 	  || REGNO (addr) == FRAME_POINTER_REGNUM)
+ 	return 1;
+       else
+ 	return 0;
+ 
+     case PLUS:
+       reg1 = 0;
+       reg2 = 0;
+       ireg = 0;
+       breg = 0;
+       offset = 0;
+       if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
+ 	{
+ 	  offset = XEXP (addr, 0);
+ 	  addr = XEXP (addr, 1);
+ 	}
+       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
+ 	{
+ 	  offset = XEXP (addr, 1);
+ 	  addr = XEXP (addr, 0);
+ 	}
+       if (GET_CODE (addr) != PLUS)
+ 	;
+       else if (GET_CODE (XEXP (addr, 0)) == MULT)
+ 	reg1 = XEXP (addr, 0), addr = XEXP (addr, 1);
+       else if (GET_CODE (XEXP (addr, 1)) == MULT)
+ 	reg1 = XEXP (addr, 1), addr = XEXP (addr, 0);
+       else if (GET_CODE (XEXP (addr, 0)) == REG)
+ 	reg1 = XEXP (addr, 0), addr = XEXP (addr, 1);
+       else if (GET_CODE (XEXP (addr, 1)) == REG)
+ 	reg1 = XEXP (addr, 1), addr = XEXP (addr, 0);
+ 
+       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
+ 	{
+ 	  if (reg1 == 0)
+ 	    reg1 = addr;
+ 	  else
+ 	    reg2 = addr;
+ 
+ 	  addr = 0;
+ 	}
+ 
+       if (offset != 0)
+ 	{
+ 	  if (addr != 0)
+ 	    abort ();
+ 	  addr = offset;
+ 	}
+ 
+       if ((reg1 && GET_CODE (reg1) == MULT)
+ 	  || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
+ 	{
+ 	  breg = reg2;
+ 	  ireg = reg1;
+ 	}
+       else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
+ 	{
+ 	  breg = reg1;
+ 	  ireg = reg2;
+ 	}
+ 
+       if (ireg != 0 || breg != 0)
+ 	{
+ 	  int scale = 1;
+ 	  int size;
+ 
+ 	  if (addr != 0)
+ 	    {
+ 	      if (GET_CODE (addr) == CONST_INT
+ 		  && INTVAL (addr) >= -128 && INTVAL (addr) < 128)
+ 		size = 1;
+ 	      else
+ 		size = 4;
+ 	    }
+ 
+ 	  if (ireg != 0 && GET_CODE (ireg) == MULT)
+ 	    {
+ 	      scale = INTVAL (XEXP (ireg, 1));
+ 	      ireg = XEXP (ireg, 0);
+ 	    }
+ 
+ 	  /* The stack pointer can only appear as a base register,
+ 	     never an index register, so exchange the regs if it is wrong. */
+ 
+ 	  if (scale == 1 && ireg && REGNO (ireg) == STACK_POINTER_REGNUM)
+ 	    {
+ 	      rtx tmp;
+ 
+ 	      tmp = breg;
+ 	      breg = ireg;
+ 	      ireg = tmp;
+ 	    }
+ 
+ 	  if (!ireg)
+ 	    return size;
+ 
+ 	  /* We need SIB here.  */
+ 	  return size + 1;
+ 	}
+     case MULT:
+       {
+ 	int scale;
+ 
+ 	if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
+ 	  {
+ 	    scale = INTVAL (XEXP (addr, 0));
+ 	    ireg = XEXP (addr, 1);
+ 	  }
+ 	else
+ 	  {
+ 	    scale = INTVAL (XEXP (addr, 1));
+ 	    ireg = XEXP (addr, 0);
+ 	  }
+ 
+ 	if (scale == 2)
+ 	  return 1;		/* SIB */
+ 	else
+ 	  return 2;		/* SIB + emty address.  */
+       }
+     default:
+       /* Symbol references and constaints takes 4 bytes.  */
+       return 4;
+     }
+ }
+ 
  /* Print a memory operand whose address is ADDR.  */
  
  void
*** i386.h1	Tue Apr 13 12:50:37 1999
--- i386.h	Tue Apr 13 12:35:02 1999
*************** extern char *output_fp_conditional_move 
*** 2765,2770 ****
--- 2765,2771 ----
  extern int ix86_can_use_return_insn_p ();
  extern int small_shift_operand ();
  extern char *output_ashlsi3 ();
+ extern int memory_address_size ();
  
  #ifdef NOTYET
  extern struct rtx_def *copy_all_rtx ();


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