This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Function to compute size of i386 adress operand.
- To: egcs-patches at egcs dot cygnus dot com
- Subject: Function to compute size of i386 adress operand.
- From: Jan Hubicka <hubicka at atrey dot karlin dot mff dot cuni dot cz>
- Date: Tue, 13 Apr 1999 13:39:58 +0200
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 ();