diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-03-28 09:26:28 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-03-28 09:26:28 +0000 |
commit | 9fd68c082693e2db323eee226f8f041a1a596cc9 (patch) | |
tree | 60bd2c4c9dd96be75e26bf7a55c401eb632b6850 /gcc/config/i386/i386.c | |
parent | 9f9d16c921fcede880ddba43b970b29f0f888d8f (diff) |
Merge from mainlinebefore_gc_merge_990902egcs_gc_branch
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/egcs_gc_branch@26036 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/i386/i386.c')
-rw-r--r-- | gcc/config/i386/i386.c | 147 |
1 files changed, 101 insertions, 46 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 1d370657622..dad8c90e8e6 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -1,5 +1,5 @@ /* Subroutines for insn-output.c for Intel X86. - Copyright (C) 1988, 92, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. + Copyright (C) 1988, 92, 94-98, 1999 Free Software Foundation, Inc. This file is part of GNU CC. @@ -622,9 +622,19 @@ i386_valid_type_attribute_p (type, attributes, identifier, args) int i386_comp_type_attributes (type1, type2) - tree type1 ATTRIBUTE_UNUSED; - tree type2 ATTRIBUTE_UNUSED; + tree type1; + tree type2; { + /* Check for mismatch of non-default calling convention. */ + char *rtdstr = TARGET_RTD ? "cdecl" : "stdcall"; + + if (TREE_CODE (type1) != FUNCTION_TYPE) + return 1; + + /* Check for mismatched return types (cdecl vs stdcall). */ + if (!lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type1)) + != !lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type2))) + return 0; return 1; } @@ -2079,6 +2089,62 @@ load_pic_register (do_rtl) emit_insn (gen_blockage ()); } +/* Compute the size of local storage taking into consideration the + desired stack alignment which is to be maintained. Also determine + the number of registers saved below the local storage. */ + +HOST_WIDE_INT +ix86_compute_frame_size (size, nregs_on_stack) + HOST_WIDE_INT size; + int *nregs_on_stack; +{ + int limit; + int nregs; + int regno; + int padding; + int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table + || current_function_uses_const_pool); + HOST_WIDE_INT total_size; + + limit = frame_pointer_needed + ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM; + + nregs = 0; + + for (regno = limit - 1; regno >= 0; regno--) + if ((regs_ever_live[regno] && ! call_used_regs[regno]) + || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) + nregs++; + + padding = 0; + total_size = size + (nregs * UNITS_PER_WORD); + +#ifdef PREFERRED_STACK_BOUNDARY + { + int offset; + int preferred_alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT; + + offset = 4; + if (frame_pointer_needed) + offset += UNITS_PER_WORD; + + total_size += offset; + + padding = ((total_size + preferred_alignment - 1) + & -preferred_alignment) - total_size; + + if (padding < (((offset + preferred_alignment - 1) + & -preferred_alignment) - offset)) + padding += preferred_alignment; + } +#endif + + if (nregs_on_stack) + *nregs_on_stack = nregs; + + return size + padding; +} + static void ix86_prologue (do_rtl) int do_rtl; @@ -2088,7 +2154,7 @@ ix86_prologue (do_rtl) rtx xops[4]; int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table || current_function_uses_const_pool); - long tsize = get_frame_size (); + HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), (int *)0); rtx insn; int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset; @@ -2301,32 +2367,18 @@ ix86_epilogue (do_rtl) int do_rtl; { register int regno; - register int nregs, limit; - int offset; + register int limit; + int nregs; rtx xops[3]; int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table || current_function_uses_const_pool); - long tsize = get_frame_size (); - - /* Compute the number of registers to pop */ - - limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); + int sp_valid = !frame_pointer_needed || current_function_sp_is_unchanging; + HOST_WIDE_INT offset; + HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), &nregs); - nregs = 0; - - for (regno = limit - 1; regno >= 0; regno--) - if ((regs_ever_live[regno] && ! call_used_regs[regno]) - || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) - nregs++; - - /* sp is often unreliable so we must go off the frame pointer. - - In reality, we may not care if sp is unreliable, because we can restore - the register relative to the frame pointer. In theory, since each move - is the same speed as a pop, and we don't need the leal, this is faster. - For now restore multiple registers the old way. */ + /* sp is often unreliable so we may have to go off the frame pointer. */ - offset = - tsize - (nregs * UNITS_PER_WORD); + offset = -(tsize + nregs * UNITS_PER_WORD); xops[2] = stack_pointer_rtx; @@ -2341,9 +2393,17 @@ ix86_epilogue (do_rtl) if (flag_pic || profile_flag || profile_block_flag) emit_insn (gen_blockage ()); - if (nregs > 1 || ! frame_pointer_needed) + /* If we're only restoring one register and sp is not valid then + using a move instruction to restore the register since it's + less work than reloading sp and popping the register. Otherwise, + restore sp (if necessary) and pop the registers. */ + + limit = frame_pointer_needed + ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM; + + if (nregs > 1 || sp_valid) { - if (frame_pointer_needed) + if ( !sp_valid ) { xops[0] = adj_offsettable_operand (AT_BP (QImode), offset); if (do_rtl) @@ -2550,7 +2610,7 @@ do { \ } \ } while (0) -static int +int legitimate_pic_address_disp_p (disp) register rtx disp; { @@ -2602,7 +2662,7 @@ legitimate_address_p (mode, addr, strict) } if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG) - base = addr; + base = addr; else if (GET_CODE (addr) == PLUS) { @@ -2692,6 +2752,12 @@ legitimate_address_p (mode, addr, strict) return FALSE; } + if (GET_MODE (base) != Pmode) + { + ADDR_INVALID ("Base is not in Pmode.\n", base); + return FALSE; + } + if ((strict && ! REG_OK_FOR_BASE_STRICT_P (base)) || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (base))) { @@ -2713,6 +2779,12 @@ legitimate_address_p (mode, addr, strict) return FALSE; } + if (GET_MODE (indx) != Pmode) + { + ADDR_INVALID ("Index is not in Pmode.\n", indx); + return FALSE; + } + if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (indx)) || (! strict && ! REG_OK_FOR_INDEX_NONSTRICT_P (indx))) { @@ -5423,12 +5495,6 @@ output_fp_conditional_move (which_alternative, operands) output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); break; - case 2: - /* r <- cond ? r : arg */ - output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); - output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); - break; - default: abort (); } @@ -5488,17 +5554,6 @@ output_int_conditional_move (which_alternative, operands) output_asm_insn (AS2 (cmov%c1,%3,%0), xops); break; - case 2: - /* rm <- cond ? arg1 : arg2 */ - output_asm_insn (AS2 (cmov%C1,%2,%0), operands); - output_asm_insn (AS2 (cmov%c1,%3,%0), operands); - if (mode == DImode) - { - output_asm_insn (AS2 (cmov%C1,%2,%0), xops); - output_asm_insn (AS2 (cmov%c1,%3,%0), xops); - } - break; - default: abort (); } |