i386.c (struct machine_function): Add save_varrargs_registers.
authorJan Hubicka <jh@suse.cz>
Mon, 26 Mar 2001 12:36:35 +0000 (14:36 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Mon, 26 Mar 2001 12:36:35 +0000 (12:36 +0000)
* i386.c (struct machine_function): Add save_varrargs_registers.
(ix86_save_varrargs_registers): New macro.
(ix86_frame_layout): Support 64bit; support red zones and varrargs area.
(ix86_expand_prologue): Likewise.
(ix86_emit_epilogue_esp_adjustement): Likewise.
(ix86_expand_epilogue): Likewise.
* i386.md (pro_epilogue_adjust_stack): Turn to expander; support 64bit.
(pro_epilogue_adjust_stack_1): New insn.
(pro_epilogue_adjust_stack_rex64): Likewise.
* i386.h (MASK_NO_RED_ZONE): New constant.
(TARGET_RED_ZONE): New macro.
(TARGET_OPTIONS): Add "red-zone" and "no-red-zone"
(RED_ZONE_SIZE): New constant.
(RED_ZONE_RESERVE): New constant.

From-SVN: r40846

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/i386/i386.md

index 55ef8ed99f00f3485da91232c43e89b065860eed..db3c86df5d559fa0d1a30dc056bf0c87d8c67f88 100644 (file)
@@ -1,3 +1,20 @@
+Mon Mar 26 14:35:18 CEST 2001  Jan Hubicka  <jh@suse.cz>
+
+       * i386.c (struct machine_function): Add save_varrargs_registers.
+       (ix86_save_varrargs_registers): New macro.
+       (ix86_frame_layout): Support 64bit; support red zones and varrargs area.
+       (ix86_expand_prologue): Likewise.
+       (ix86_emit_epilogue_esp_adjustement): Likewise.
+       (ix86_expand_epilogue): Likewise.
+       * i386.md (pro_epilogue_adjust_stack): Turn to expander; support 64bit.
+       (pro_epilogue_adjust_stack_1): New insn.
+       (pro_epilogue_adjust_stack_rex64): Likewise.
+       * i386.h (MASK_NO_RED_ZONE): New constant.
+       (TARGET_RED_ZONE): New macro.
+       (TARGET_OPTIONS): Add "red-zone" and "no-red-zone"
+       (RED_ZONE_SIZE): New constant.
+       (RED_ZONE_RESERVE): New constant.
+
 2001-03-25  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * toplev.c (set_float_handler): Use memcpy, not bcopy.
index fa6633d22602dbf09ba753775da76424dedf32aa..b12d625652377a535d3dcf4953c794cc576d380c 100644 (file)
@@ -442,15 +442,19 @@ struct rtx_def *ix86_compare_op0 = NULL_RTX;
 struct rtx_def *ix86_compare_op1 = NULL_RTX;
 
 #define MAX_386_STACK_LOCALS 2
+/* Size of the register save area.  */
+#define X86_64_VARARGS_SIZE (REGPARM_MAX * UNITS_PER_WORD + SSE_REGPARM_MAX * 16)
 
 /* Define the structure for the machine field in struct function.  */
 struct machine_function
 {
   rtx stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
+  int save_varrargs_registers;
   int accesses_prev_frame;
 };
 
 #define ix86_stack_locals (cfun->machine->stack_locals)
+#define ix86_save_varrargs_registers (cfun->machine->save_varrargs_registers)
 
 /* Structure describing stack frame layout.
    Stack grows downward:
@@ -475,9 +479,11 @@ struct ix86_frame
 {
   int nregs;
   int padding1;
+  int va_arg_size;
   HOST_WIDE_INT frame;
   int padding2;
   int outgoing_arguments_size;
+  int red_zone_size;
 
   HOST_WIDE_INT to_allocate;
   /* The offsets relative to ARG_POINTER.  */
@@ -2338,6 +2344,15 @@ ix86_compute_frame_layout (frame)
   /* Register save area */
   offset += frame->nregs * UNITS_PER_WORD;
 
+  /* Va-arg area */
+  if (ix86_save_varrargs_registers)
+    {
+      offset += X86_64_VARARGS_SIZE;
+      frame->va_arg_size = X86_64_VARARGS_SIZE;
+    }
+  else
+    frame->va_arg_size = 0;
+
   /* Align start of frame for local function.  */
   frame->padding1 = ((offset + stack_alignment_needed - 1)
                     & -stack_alignment_needed) - offset;
@@ -2370,15 +2385,28 @@ ix86_compute_frame_layout (frame)
   /* Size prologue needs to allocate.  */
   frame->to_allocate =
     (size + frame->padding1 + frame->padding2
-     + frame->outgoing_arguments_size);
+     + frame->outgoing_arguments_size + frame->va_arg_size);
 
+  if (TARGET_64BIT && TARGET_RED_ZONE && current_function_sp_is_unchanging
+      && current_function_is_leaf)
+    {
+      frame->red_zone_size = frame->to_allocate;
+      if (frame->red_zone_size > RED_ZONE_SIZE - RED_ZONE_RESERVE)
+       frame->red_zone_size = RED_ZONE_SIZE - RED_ZONE_RESERVE;
+    }
+  else
+    frame->red_zone_size = 0;
+  frame->to_allocate -= frame->red_zone_size;
+  frame->stack_pointer_offset -= frame->red_zone_size;
 #if 0
   fprintf (stderr, "nregs: %i\n", frame->nregs);
   fprintf (stderr, "size: %i\n", size);
   fprintf (stderr, "alignment1: %i\n", stack_alignment_needed);
   fprintf (stderr, "padding1: %i\n", frame->padding1);
+  fprintf (stderr, "va_arg: %i\n", frame->va_arg_size);
   fprintf (stderr, "padding2: %i\n", frame->padding2);
   fprintf (stderr, "to_allocate: %i\n", frame->to_allocate);
+  fprintf (stderr, "red_zone_size: %i\n", frame->red_zone_size);
   fprintf (stderr, "frame_pointer_offset: %i\n", frame->frame_pointer_offset);
   fprintf (stderr, "hard_frame_pointer_offset: %i\n",
           frame->hard_frame_pointer_offset);
@@ -2438,8 +2466,12 @@ ix86_expand_prologue ()
                          (stack_pointer_rtx, stack_pointer_rtx,
                           GEN_INT (-frame.to_allocate), hard_frame_pointer_rtx));
       else
-        insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                                     GEN_INT (-frame.to_allocate)));
+       if (TARGET_64BIT)
+         insn = emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
+                                       GEN_INT (-frame.to_allocate)));
+        else
+         insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+                                       GEN_INT (-frame.to_allocate)));
       RTX_FRAME_RELATED_P (insn) = 1;
     }
   else
@@ -2448,6 +2480,9 @@ ix86_expand_prologue ()
 
       rtx arg0, sym;
 
+      if (TARGET_64BIT)
+       abort();
+
       arg0 = gen_rtx_REG (SImode, 0);
       emit_move_insn (arg0, GEN_INT (frame.to_allocate));
 
@@ -2489,8 +2524,12 @@ ix86_emit_epilogue_esp_adjustment (tsize)
                                              GEN_INT (tsize),
                                              hard_frame_pointer_rtx));
   else
-    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                          GEN_INT (tsize)));
+    if (TARGET_64BIT)
+      emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
+                            GEN_INT (tsize)));
+    else
+      emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+                            GEN_INT (tsize)));
 }
 
 /* Emit code to restore saved registers using MOV insns.  First register
@@ -2563,18 +2602,20 @@ ix86_expand_epilogue (emit_return)
        ix86_emit_restore_regs_using_mov (hard_frame_pointer_rtx, offset);
 
       if (!frame_pointer_needed)
-       ix86_emit_epilogue_esp_adjustment (frame.to_allocate
-                                          + frame.nregs * UNITS_PER_WORD);
+       ix86_emit_epilogue_esp_adjustment (frame.to_allocate + frame.nregs * UNITS_PER_WORD);
       /* If not an i386, mov & pop is faster than "leave".  */
       else if (TARGET_USE_LEAVE || optimize_size)
-       emit_insn (gen_leave ());
+       emit_insn (TARGET_64BIT ? gen_leave_rex64 () : gen_leave ());
       else
        {
          emit_insn (gen_pro_epilogue_adjust_stack (stack_pointer_rtx,
                                                    hard_frame_pointer_rtx,
                                                    const0_rtx,
                                                    hard_frame_pointer_rtx));
-         emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
+         if (TARGET_64BIT)
+           emit_insn (gen_popdi1 (hard_frame_pointer_rtx));
+         else
+           emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
        }
     }
   else
@@ -2595,9 +2636,19 @@ ix86_expand_epilogue (emit_return)
 
       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
        if (ix86_save_reg (regno))
-         emit_insn (gen_popsi1 (gen_rtx_REG (SImode, regno)));
+         {
+           if (TARGET_64BIT)
+             emit_insn (gen_popdi1 (gen_rtx_REG (Pmode, regno)));
+           else
+             emit_insn (gen_popsi1 (gen_rtx_REG (Pmode, regno)));
+         }
       if (frame_pointer_needed)
-       emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
+       {
+         if (TARGET_64BIT)
+           emit_insn (gen_popdi1 (hard_frame_pointer_rtx));
+         else
+           emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
+       }
     }
 
   /* Sibcall epilogues don't want a return instruction.  */
@@ -2616,6 +2667,10 @@ ix86_expand_epilogue (emit_return)
        {
          rtx ecx = gen_rtx_REG (SImode, 2);
 
+         /* There are is no "pascal" calling convention in 64bit ABI.  */
+         if (TARGET_64BIT)
+           abort();
+
          emit_insn (gen_popsi1 (ecx));
          emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, popc));
          emit_jump_insn (gen_return_indirect_internal (ecx));
index 7312108dfcb39208f94d5f5cba4cc01e30e49ed7..1552b413efce98dda5bba80c01685aad8c7fc4bb 100644 (file)
@@ -120,6 +120,7 @@ extern int target_flags;
 #define MASK_128BIT_LONG_DOUBLE 0x00080000     /* long double size is 128bit */
 #define MASK_MIX_SSE_I387      0x00100000      /* Mix SSE and i387 instructions */
 #define MASK_64BIT             0x00200000      /* Produce 64bit code */
+#define MASK_NO_RED_ZONE       0x00400000      /* Do not use red zone */
 
 /* Temporary codegen switches */
 #define MASK_INTEL_SYNTAX      0x00000200
@@ -250,6 +251,8 @@ extern const int x86_partial_reg_dependency, x86_memory_mismatch_stall;
 #define TARGET_MIX_SSE_I387 ((target_flags & MASK_MIX_SSE_I387) != 0)
 #define TARGET_MMX ((target_flags & MASK_MMX) != 0)
 
+#define TARGET_RED_ZONE (!(target_flags & MASK_NO_RED_ZONE))
+
 #define TARGET_SWITCHES                                                              \
 { { "80387",                    MASK_80387, N_("Use hardware fp") },         \
   { "no-80387",                        -MASK_80387, N_("Do not use hardware fp") },  \
@@ -338,6 +341,10 @@ extern const int x86_partial_reg_dependency, x86_memory_mismatch_stall;
     N_("Generate 64bit x86-64 code") },                                              \
   { "32",                      -MASK_64BIT,                                  \
     N_("Generate 32bit i386 code") },                                        \
+  { "red-zone",                        -MASK_NO_RED_ZONE,                            \
+    N_("Use red-zone in the x86-64 code") },                                 \
+  { "no-red-zone",             MASK_NO_RED_ZONE,                             \
+    N_("do not use red-zone in the x86-64 code") },                          \
   SUBTARGET_SWITCHES                                                         \
   { "", TARGET_DEFAULT, 0 }}
 
@@ -3106,6 +3113,10 @@ enum cmodel {
   CM_SMALL_PIC
 };
 
+/* Size of the RED_ZONE area.  */
+#define RED_ZONE_SIZE 128
+/* Reserved area of the red zone for temporaries.  */
+#define RED_ZONE_RESERVE 8
 /* Valud of -mcmodel specified by user.  */
 extern const char *ix86_cmodel_string;
 extern enum cmodel ix86_cmodel;
index 4850ca491b1617fcda40933a0ec3f728d6d46da8..6a23023f2795e6d43ae8ead10290e6107c241ec1 100644 (file)
        (zero_extend:DI
          (minus:SI (match_dup 1)
                    (match_dup 2))))]
-  "ix86_match_ccmode (insn, CCmode)
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
    && ix86_binary_operator_ok (MINUS, SImode, operands)"
   "sub{q}\\t{%2, %0|%0, %2}"
   [(set_attr "type" "alu")
    (set_attr "modrm" "0")
    (set_attr "athlon_decode" "vector")
    (set_attr "ppro_uops" "few")])
+
+(define_insn "leave_rex64"
+  [(set (reg:DI 7) (reg:DI 6))
+   (set (reg:DI 6) (mem:DI (pre_dec:DI (reg:DI 7))))]
+  "TARGET_64BIT"
+  "leave"
+  [(set_attr "length_immediate" "0")
+   (set_attr "length" "1")
+   (set_attr "modrm" "0")
+   (set_attr "modrm" "0")
+   (set_attr "athlon_decode" "vector")
+   (set_attr "ppro_uops" "few")])
 \f
 (define_expand "ffssi2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "") 
 ;; [(set (mem (plus (reg ebp) (const_int -160000))) (const_int 0))]
 ;;
 ;; in proper program order.
+(define_expand "pro_epilogue_adjust_stack"
+  [(parallel [(set (match_operand:SI 0 "register_operand" "=r,r")
+                  (plus:SI (match_operand:SI 1 "register_operand" "0,r")
+                           (match_operand:SI 2 "immediate_operand" "i,i")))
+             (set (match_operand:SI 3 "register_operand" "+r,r")
+                  (match_dup 3))
+             (clobber (reg:CC 17))])]
+ ""
+ "
+{
+  if (TARGET_64BIT)
+    {
+      emit_insn (gen_pro_epilogue_adjust_stack_rex64 (operands[0], operands[1],
+                                                     operands[2], operands[3]));
+      DONE;
+    }
+}")
 
-(define_insn "pro_epilogue_adjust_stack"
+(define_insn "*pro_epilogue_adjust_stack_1"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (plus:SI (match_operand:SI 1 "register_operand" "0,r")
                 (match_operand:SI 2 "immediate_operand" "i,i")))
    (set (match_operand:SI 3 "register_operand" "+r,r")
        (match_dup 3))
    (clobber (reg:CC 17))]
-  ""
+  "!TARGET_64BIT"
   "*
 {
   switch (get_attr_type (insn))
              (const_string "lea")))
    (set_attr "mode" "SI")])
 
+(define_insn "pro_epilogue_adjust_stack_rex64"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (plus:DI (match_operand:DI 1 "register_operand" "0,r")
+                (match_operand:DI 2 "x86_64_immediate_operand" "e,e")))
+   (set (match_operand:DI 3 "register_operand" "+r,r")
+       (match_dup 3))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_IMOV:
+      return \"mov{q}\\t{%1, %0|%0, %1}\";
+
+    case TYPE_ALU:
+      if (GET_CODE (operands[2]) == CONST_INT
+          && (INTVAL (operands[2]) == 128
+             || (INTVAL (operands[2]) < 0
+                 && INTVAL (operands[2]) != -128)))
+       {
+         operands[2] = GEN_INT (-INTVAL (operands[2]));
+         return \"sub{q}\\t{%2, %0|%0, %2}\";
+       }
+      return \"add{q}\\t{%2, %0|%0, %2}\";
+
+    case TYPE_LEA:
+      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
+      return \"lea{q}\\t{%a2, %0|%0, %a2}\";
+
+    default:
+      abort ();
+    }
+}"
+  [(set (attr "type")
+       (cond [(eq_attr "alternative" "0")
+                (const_string "alu")
+              (match_operand:DI 2 "const0_operand" "")
+                (const_string "imov")
+             ]
+             (const_string "lea")))
+   (set_attr "mode" "DI")])
+
+
 ;; Placeholder for the conditional moves.  This one is split eighter to SSE
 ;; based moves emulation or to usual cmove sequence.  Little bit unfortunate
 ;; fact is that compares supported by the cmp??ss instructions are exactly