i386.h (FIRST_PSEUDO_REGISTER): Set to 21.
* i386.h (FIRST_PSEUDO_REGISTER): Set to 21. (FIXED_REGISTERS, CALL_USED_REGISTERS, REG_ALLOC_ORDER): Add frame pointer (FRAME_POINTER_REGNUM): Set to 20 (HARD_FRAME_POINTER_REGNUM): New macro. (ELIMINABLE_REGS): Eliminate ARG_POINTER and FRAME_POINTER to HARD_FRAME_POINTER. (REGNO_OK_FOR_BASE_P): Accept FRAME_POINTER_REGNUM (REG_OK_FOR_INDEX_NONSTRICT_P): Likewise. (REG_OK_FOR_BASE_NONSTRICT_P): Likewise. (HI_REGISTER_NAMES): Add "frame". (CAN_ELIMINATE): Handle FRAME_POINTER_REGNUM elimination. (debug_reg): Handle FRAME_POINTER_REGNUM. (reg_class): Add arg pointer and frame pointer to NON_Q_REGS, GENERAL_REGS and INDEX_REGS. * i386.c (SAVED_REGS_FIRST): new macro. (AT_BP): Use hard_frame_pointer_rtx instead of frame_pointer_rtx (ix86_decompose_address, memory_address_length): Likewise. (regclass_map): Add frame pointer. (call_insn_operand): Handle frame_pointer_rtx. (reg_no_sp_operand): Likewise. (ix86_decompose_address): Handle frame_pointer_rtx as stack_pointer_rtx. (print_operand, legitimize_pic_address): Fix formating. (ix86_compute_frame_size): Make static, update prototype, new parameters padding1, padding2, use ix86_nsaved_regs, use stack_alignment_needed. (ix86_initial_elimination_offset): Handle FRAME_POINTER_REGNUM to HARD_FRAME_POINTER_REGNUM conversions. (ix86_expand_prologue): Handle SAVED_REGS_FIRST prologues. (ix86_expand_epilogue): Handle SAVED_REGS_FIRST epilogues. (print_reg): Abort on FRAME_POINTER_REGNUM From-SVN: r31587
This commit is contained in:
parent
2247f6ed8d
commit
564d80f490
3 changed files with 234 additions and 101 deletions
|
@ -1,3 +1,37 @@
|
|||
Mon Jan 24 17:37:31 MET 2000 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* i386.h (FIRST_PSEUDO_REGISTER): Set to 21.
|
||||
(FIXED_REGISTERS, CALL_USED_REGISTERS,
|
||||
REG_ALLOC_ORDER): Add frame pointer
|
||||
(FRAME_POINTER_REGNUM): Set to 20
|
||||
(HARD_FRAME_POINTER_REGNUM): New macro.
|
||||
(ELIMINABLE_REGS): Eliminate ARG_POINTER and FRAME_POINTER
|
||||
to HARD_FRAME_POINTER.
|
||||
(REGNO_OK_FOR_BASE_P): Accept FRAME_POINTER_REGNUM
|
||||
(REG_OK_FOR_INDEX_NONSTRICT_P): Likewise.
|
||||
(REG_OK_FOR_BASE_NONSTRICT_P): Likewise.
|
||||
(HI_REGISTER_NAMES): Add "frame".
|
||||
(CAN_ELIMINATE): Handle FRAME_POINTER_REGNUM elimination.
|
||||
(debug_reg): Handle FRAME_POINTER_REGNUM.
|
||||
(reg_class): Add arg pointer and frame pointer to NON_Q_REGS,
|
||||
GENERAL_REGS and INDEX_REGS.
|
||||
* i386.c (SAVED_REGS_FIRST): new macro.
|
||||
(AT_BP): Use hard_frame_pointer_rtx instead of frame_pointer_rtx
|
||||
(ix86_decompose_address, memory_address_length): Likewise.
|
||||
(regclass_map): Add frame pointer.
|
||||
(call_insn_operand): Handle frame_pointer_rtx.
|
||||
(reg_no_sp_operand): Likewise.
|
||||
(ix86_decompose_address): Handle frame_pointer_rtx as stack_pointer_rtx.
|
||||
(print_operand, legitimize_pic_address): Fix formating.
|
||||
(ix86_compute_frame_size): Make static, update prototype, new
|
||||
parameters padding1, padding2, use ix86_nsaved_regs, use
|
||||
stack_alignment_needed.
|
||||
(ix86_initial_elimination_offset): Handle FRAME_POINTER_REGNUM
|
||||
to HARD_FRAME_POINTER_REGNUM conversions.
|
||||
(ix86_expand_prologue): Handle SAVED_REGS_FIRST prologues.
|
||||
(ix86_expand_epilogue): Handle SAVED_REGS_FIRST epilogues.
|
||||
(print_reg): Abort on FRAME_POINTER_REGNUM
|
||||
|
||||
Mon Jan 24 16:50:08 MET 2000 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* i386.h (PREDICATE_CODES): Add aligned_operand.
|
||||
|
|
|
@ -41,6 +41,16 @@ Boston, MA 02111-1307, USA. */
|
|||
#include "basic-block.h"
|
||||
#include "ggc.h"
|
||||
|
||||
/* True when we want to do pushes before allocating stack to get better
|
||||
scheduling.
|
||||
|
||||
Saving registers first is win in the most cases except for LEAVE
|
||||
instruction. Macro is 0 iff we will use LEAVE. */
|
||||
|
||||
#define SAVED_REGS_FIRST \
|
||||
(!frame_pointer_needed || (!TARGET_USE_LEAVE && !optimize_size))
|
||||
|
||||
|
||||
#ifdef EXTRA_CONSTRAINT
|
||||
/* If EXTRA_CONSTRAINT is defined, then the 'S'
|
||||
constraint in REG_CLASS_FROM_LETTER will no longer work, and various
|
||||
|
@ -214,7 +224,7 @@ const int x86_split_long_moves = m_PPRO;
|
|||
const int x86_promote_QImode = m_K6 | m_PENT | m_386 | m_486;
|
||||
const int x86_single_stringop = m_386;
|
||||
|
||||
#define AT_BP(mode) (gen_rtx_MEM ((mode), frame_pointer_rtx))
|
||||
#define AT_BP(mode) (gen_rtx_MEM ((mode), hard_frame_pointer_rtx))
|
||||
|
||||
const char * const hi_reg_name[] = HI_REGISTER_NAMES;
|
||||
const char * const qi_reg_name[] = QI_REGISTER_NAMES;
|
||||
|
@ -234,8 +244,8 @@ enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER] =
|
|||
FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS,
|
||||
/* arg pointer */
|
||||
NON_Q_REGS,
|
||||
/* flags, fpsr, dirflag */
|
||||
NO_REGS, NO_REGS, NO_REGS
|
||||
/* flags, fpsr, dirflag, frame */
|
||||
NO_REGS, NO_REGS, NO_REGS, NON_Q_REGS
|
||||
};
|
||||
|
||||
/* The "default" register map. */
|
||||
|
@ -397,7 +407,8 @@ static void ix86_init_machine_status PARAMS ((struct function *));
|
|||
static void ix86_mark_machine_status PARAMS ((struct function *));
|
||||
static void ix86_split_to_parts PARAMS ((rtx, rtx *, enum machine_mode));
|
||||
static int ix86_safe_length_prefix PARAMS ((rtx));
|
||||
static HOST_WIDE_INT ix86_compute_frame_size PARAMS((HOST_WIDE_INT, int *));
|
||||
static HOST_WIDE_INT ix86_compute_frame_size PARAMS((HOST_WIDE_INT,
|
||||
int *, int *, int *));
|
||||
static int ix86_nsaved_regs PARAMS((void));
|
||||
static void ix86_emit_save_regs PARAMS((void));
|
||||
static void ix86_emit_restore_regs PARAMS((void));
|
||||
|
@ -1051,6 +1062,7 @@ call_insn_operand (op, mode)
|
|||
compiler aborts when trying to eliminate them. */
|
||||
if (GET_CODE (op) == REG
|
||||
&& (op == arg_pointer_rtx
|
||||
|| op == frame_pointer_rtx
|
||||
|| (REGNO (op) >= FIRST_PSEUDO_REGISTER
|
||||
&& REGNO (op) <= LAST_VIRTUAL_REGISTER)))
|
||||
return 0;
|
||||
|
@ -1150,7 +1162,7 @@ reg_no_sp_operand (op, mode)
|
|||
rtx t = op;
|
||||
if (GET_CODE (t) == SUBREG)
|
||||
t = SUBREG_REG (t);
|
||||
if (t == stack_pointer_rtx || t == arg_pointer_rtx)
|
||||
if (t == stack_pointer_rtx || t == arg_pointer_rtx || t == frame_pointer_rtx)
|
||||
return 0;
|
||||
|
||||
return register_operand (op, mode);
|
||||
|
@ -1644,91 +1656,133 @@ ix86_initial_elimination_offset (from, to)
|
|||
int from;
|
||||
int to;
|
||||
{
|
||||
if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
|
||||
return 8; /* Skip saved PC and previous frame pointer */
|
||||
int padding1;
|
||||
int nregs;
|
||||
|
||||
/* Stack grows downward:
|
||||
|
||||
[arguments]
|
||||
<- ARG_POINTER
|
||||
saved pc
|
||||
|
||||
saved frame pointer if frame_pointer_needed
|
||||
<- HARD_FRAME_POINTER
|
||||
[saved regs if SAVED_REGS_FIRST]
|
||||
|
||||
[padding1] \
|
||||
| <- FRAME_POINTER
|
||||
[frame] > tsize
|
||||
|
|
||||
[padding2] /
|
||||
|
||||
[saved regs if !SAVED_REGS_FIRST]
|
||||
<- STACK_POINTER
|
||||
*/
|
||||
|
||||
if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
|
||||
/* Skip saved PC and previous frame pointer.
|
||||
Executed only when frame_pointer_needed. */
|
||||
return 8;
|
||||
else if (from == FRAME_POINTER_REGNUM
|
||||
&& to == HARD_FRAME_POINTER_REGNUM)
|
||||
{
|
||||
ix86_compute_frame_size (get_frame_size (), &nregs, &padding1, (int *)0);
|
||||
if (SAVED_REGS_FIRST)
|
||||
padding1 += nregs * UNITS_PER_WORD;
|
||||
return -padding1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int nregs;
|
||||
int poffset;
|
||||
int offset;
|
||||
int preferred_alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
|
||||
/* ARG_POINTER or FRAME_POINTER to STACK_POINTER elimination. */
|
||||
int frame_size = frame_pointer_needed ? 8 : 4;
|
||||
HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (),
|
||||
&nregs);
|
||||
&nregs, &padding1, (int *)0);
|
||||
|
||||
offset = (tsize + nregs * UNITS_PER_WORD);
|
||||
|
||||
poffset = 4;
|
||||
if (frame_pointer_needed)
|
||||
poffset += UNITS_PER_WORD;
|
||||
|
||||
if (from == ARG_POINTER_REGNUM)
|
||||
offset += poffset;
|
||||
if (to != STACK_POINTER_REGNUM)
|
||||
abort ();
|
||||
else if (from == ARG_POINTER_REGNUM)
|
||||
return tsize + nregs * UNITS_PER_WORD + frame_size;
|
||||
else if (from != FRAME_POINTER_REGNUM)
|
||||
abort ();
|
||||
else if (SAVED_REGS_FIRST)
|
||||
return tsize - padding1;
|
||||
else
|
||||
offset -= ((poffset + preferred_alignment - 1)
|
||||
& -preferred_alignment) - poffset;
|
||||
return offset;
|
||||
return tsize + nregs * UNITS_PER_WORD - padding1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
the number of registers saved below the local storage.
|
||||
|
||||
PADDING1 returns padding before stack frame and PADDING2 returns
|
||||
padding after stack frame;
|
||||
*/
|
||||
|
||||
HOST_WIDE_INT
|
||||
ix86_compute_frame_size (size, nregs_on_stack)
|
||||
static HOST_WIDE_INT
|
||||
ix86_compute_frame_size (size, nregs_on_stack, rpadding1, rpadding2)
|
||||
HOST_WIDE_INT size;
|
||||
int *nregs_on_stack;
|
||||
int *rpadding1;
|
||||
int *rpadding2;
|
||||
{
|
||||
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);
|
||||
int padding1 = 0;
|
||||
int padding2 = 0;
|
||||
HOST_WIDE_INT total_size;
|
||||
int stack_alignment_needed = cfun->stack_alignment_needed / BITS_PER_UNIT;
|
||||
|
||||
limit = frame_pointer_needed
|
||||
? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM;
|
||||
nregs = ix86_nsaved_regs ();
|
||||
|
||||
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);
|
||||
total_size = size;
|
||||
|
||||
#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;
|
||||
offset = frame_pointer_needed ? 8 : 4;
|
||||
|
||||
/* When frame is not empty we ought to have recorded the alignment. */
|
||||
if (size && !stack_alignment_needed)
|
||||
abort ();
|
||||
|
||||
if (stack_alignment_needed < 4)
|
||||
stack_alignment_needed = 4;
|
||||
|
||||
if (stack_alignment_needed > preferred_alignment)
|
||||
abort ();
|
||||
|
||||
if (SAVED_REGS_FIRST)
|
||||
offset += nregs * UNITS_PER_WORD;
|
||||
else
|
||||
total_size += nregs * 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;
|
||||
/* Align start of frame for local function. */
|
||||
padding1 = ((offset + stack_alignment_needed - 1)
|
||||
& -stack_alignment_needed) - offset;
|
||||
total_size += padding1;
|
||||
|
||||
/* Don't bother aligning the stack of a leaf function
|
||||
which doesn't allocate any stack slots. */
|
||||
if (size == 0 && current_function_is_leaf)
|
||||
padding = 0;
|
||||
/* Align stack boundary. */
|
||||
if (!current_function_is_leaf)
|
||||
padding2 = ((total_size + preferred_alignment - 1)
|
||||
& -preferred_alignment) - total_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (nregs_on_stack)
|
||||
*nregs_on_stack = nregs;
|
||||
|
||||
return size + padding;
|
||||
if (rpadding1)
|
||||
*rpadding1 = padding1;
|
||||
|
||||
if (rpadding2)
|
||||
*rpadding2 = padding2;
|
||||
|
||||
return size + padding1 + padding2;
|
||||
}
|
||||
|
||||
/* Emit code to save registers in the prologue. */
|
||||
|
@ -1742,7 +1796,7 @@ ix86_emit_save_regs ()
|
|||
int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
|
||||
|| current_function_uses_const_pool);
|
||||
limit = (frame_pointer_needed
|
||||
? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
|
||||
? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
|
||||
|
||||
for (regno = limit - 1; regno >= 0; regno--)
|
||||
if ((regs_ever_live[regno] && !call_used_regs[regno])
|
||||
|
@ -1758,23 +1812,27 @@ ix86_emit_save_regs ()
|
|||
void
|
||||
ix86_expand_prologue ()
|
||||
{
|
||||
HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), (int *)0, (int *)0,
|
||||
(int *)0);
|
||||
rtx insn;
|
||||
int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
|
||||
|| current_function_uses_const_pool);
|
||||
HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), (int *)0);
|
||||
rtx insn;
|
||||
|
||||
/* Note: AT&T enter does NOT have reversed args. Enter is probably
|
||||
slower on all targets. Also sdb doesn't like it. */
|
||||
|
||||
if (frame_pointer_needed)
|
||||
{
|
||||
insn = emit_insn (gen_push (frame_pointer_rtx));
|
||||
insn = emit_insn (gen_push (hard_frame_pointer_rtx));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
|
||||
insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
|
||||
insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
if (SAVED_REGS_FIRST)
|
||||
ix86_emit_save_regs ();
|
||||
|
||||
if (tsize == 0)
|
||||
;
|
||||
else if (! TARGET_STACK_PROBE || tsize < CHECK_STACK_LIMIT)
|
||||
|
@ -1783,7 +1841,7 @@ ix86_expand_prologue ()
|
|||
insn = emit_insn (gen_prologue_allocate_stack (stack_pointer_rtx,
|
||||
stack_pointer_rtx,
|
||||
GEN_INT (-tsize),
|
||||
frame_pointer_rtx));
|
||||
hard_frame_pointer_rtx));
|
||||
else
|
||||
insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
|
||||
GEN_INT (-tsize)));
|
||||
|
@ -1807,7 +1865,9 @@ ix86_expand_prologue ()
|
|||
CALL_INSN_FUNCTION_USAGE (insn));
|
||||
}
|
||||
|
||||
ix86_emit_save_regs ();
|
||||
if (!SAVED_REGS_FIRST)
|
||||
ix86_emit_save_regs ();
|
||||
|
||||
#ifdef SUBTARGET_PROLOGUE
|
||||
SUBTARGET_PROLOGUE;
|
||||
#endif
|
||||
|
@ -1830,7 +1890,7 @@ ix86_emit_restore_regs ()
|
|||
int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
|
||||
|| current_function_uses_const_pool);
|
||||
int limit = (frame_pointer_needed
|
||||
? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
|
||||
? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
|
||||
int regno;
|
||||
|
||||
for (regno = 0; regno < limit; regno++)
|
||||
|
@ -1900,20 +1960,38 @@ ix86_expand_epilogue ()
|
|||
|| current_function_uses_const_pool);
|
||||
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);
|
||||
HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), &nregs, (int *)0,
|
||||
(int *)0);
|
||||
|
||||
/* SP is often unreliable so we may have to go off the frame pointer. */
|
||||
|
||||
offset = -(tsize + nregs * UNITS_PER_WORD);
|
||||
|
||||
if (SAVED_REGS_FIRST)
|
||||
{
|
||||
if (!sp_valid)
|
||||
{
|
||||
if (nregs)
|
||||
emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
|
||||
gen_rtx_PLUS (SImode, hard_frame_pointer_rtx,
|
||||
GEN_INT (- nregs * UNITS_PER_WORD))));
|
||||
else
|
||||
emit_insn (gen_epilogue_deallocate_stack (stack_pointer_rtx,
|
||||
hard_frame_pointer_rtx));
|
||||
}
|
||||
else if (tsize)
|
||||
ix86_emit_epilogue_esp_adjustment (tsize);
|
||||
ix86_emit_restore_regs ();
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
if (nregs > 1 || sp_valid)
|
||||
else if (nregs > 1 || sp_valid)
|
||||
{
|
||||
if ( !sp_valid )
|
||||
if (!sp_valid)
|
||||
{
|
||||
rtx addr_offset;
|
||||
addr_offset = adj_offsettable_operand (AT_BP (QImode), offset);
|
||||
|
@ -1927,7 +2005,7 @@ ix86_expand_epilogue ()
|
|||
else
|
||||
{
|
||||
limit = (frame_pointer_needed
|
||||
? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
|
||||
? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
|
||||
for (regno = 0; regno < limit; regno++)
|
||||
if ((regs_ever_live[regno] && ! call_used_regs[regno])
|
||||
|| (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
|
||||
|
@ -1941,16 +2019,17 @@ ix86_expand_epilogue ()
|
|||
if (frame_pointer_needed)
|
||||
{
|
||||
/* If not an i386, mov & pop is faster than "leave". */
|
||||
if (TARGET_USE_LEAVE)
|
||||
emit_insn (gen_leave());
|
||||
if (TARGET_USE_LEAVE || optimize_size)
|
||||
emit_insn (gen_leave ());
|
||||
else
|
||||
{
|
||||
emit_insn (gen_epilogue_deallocate_stack (stack_pointer_rtx,
|
||||
frame_pointer_rtx));
|
||||
emit_insn (gen_popsi1 (frame_pointer_rtx));
|
||||
if (!SAVED_REGS_FIRST)
|
||||
emit_insn (gen_epilogue_deallocate_stack (stack_pointer_rtx,
|
||||
hard_frame_pointer_rtx));
|
||||
emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
|
||||
}
|
||||
}
|
||||
else if (tsize)
|
||||
else if (!SAVED_REGS_FIRST && tsize)
|
||||
ix86_emit_epilogue_esp_adjustment (tsize);
|
||||
|
||||
#ifdef FUNCTION_BLOCK_PROFILER_EXIT
|
||||
|
@ -2071,7 +2150,8 @@ ix86_decompose_address (addr, out)
|
|||
|
||||
/* Allow arg pointer and stack pointer as index if there is not scaling */
|
||||
if (base && index && scale == 1
|
||||
&& (index == arg_pointer_rtx || index == stack_pointer_rtx))
|
||||
&& (index == arg_pointer_rtx || index == frame_pointer_rtx
|
||||
|| index == stack_pointer_rtx))
|
||||
{
|
||||
rtx tmp = base;
|
||||
base = index;
|
||||
|
@ -2079,7 +2159,9 @@ ix86_decompose_address (addr, out)
|
|||
}
|
||||
|
||||
/* Special case: %ebp cannot be encoded as a base without a displacement. */
|
||||
if (base == frame_pointer_rtx && !disp)
|
||||
if ((base == hard_frame_pointer_rtx
|
||||
|| base == frame_pointer_rtx
|
||||
|| base == arg_pointer_rtx) && !disp)
|
||||
disp = const0_rtx;
|
||||
|
||||
/* Special case: on K6, [%esi] makes the instruction vector decoded.
|
||||
|
@ -2388,7 +2470,7 @@ legitimize_pic_address (orig, reg)
|
|||
/* Check that the unspec is one of the ones we generate? */
|
||||
}
|
||||
else if (GET_CODE (addr) != PLUS)
|
||||
abort();
|
||||
abort ();
|
||||
}
|
||||
if (GET_CODE (addr) == PLUS)
|
||||
{
|
||||
|
@ -2807,6 +2889,7 @@ print_reg (x, code, file)
|
|||
FILE *file;
|
||||
{
|
||||
if (REGNO (x) == ARG_POINTER_REGNUM
|
||||
|| REGNO (x) == FRAME_POINTER_REGNUM
|
||||
|| REGNO (x) == FLAGS_REG
|
||||
|| REGNO (x) == FPSR_REG)
|
||||
abort ();
|
||||
|
@ -3029,7 +3112,7 @@ print_operand (file, x, code)
|
|||
case 8: size = "QWORD"; break;
|
||||
case 12: size = "XWORD"; break;
|
||||
default:
|
||||
abort();
|
||||
abort ();
|
||||
}
|
||||
fputs (size, file);
|
||||
fputs (" PTR ", file);
|
||||
|
@ -3251,7 +3334,7 @@ split_di (operands, num, lo_half, hi_half)
|
|||
hi_half[num] = change_address (op, SImode, hi_addr);
|
||||
}
|
||||
else
|
||||
abort();
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5580,7 +5663,8 @@ memory_address_length (addr)
|
|||
/* Special cases: ebp and esp need the two-byte modrm form. */
|
||||
if (addr == stack_pointer_rtx
|
||||
|| addr == arg_pointer_rtx
|
||||
|| addr == frame_pointer_rtx)
|
||||
|| addr == frame_pointer_rtx
|
||||
|| addr == hard_frame_pointer_rtx)
|
||||
len = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -619,7 +619,7 @@ extern int ix86_arch;
|
|||
eliminated during reloading in favor of either the stack or frame
|
||||
pointer. */
|
||||
|
||||
#define FIRST_PSEUDO_REGISTER 20
|
||||
#define FIRST_PSEUDO_REGISTER 21
|
||||
|
||||
/* Number of hardware registers that go into the DWARF-2 unwind info.
|
||||
If not defined, equals FIRST_PSEUDO_REGISTER. */
|
||||
|
@ -631,7 +631,9 @@ extern int ix86_arch;
|
|||
On the 80386, the stack pointer is such, as is the arg pointer. */
|
||||
#define FIXED_REGISTERS \
|
||||
/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg,flags,fpsr, dir*/ \
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, \
|
||||
/*frame */ \
|
||||
1}
|
||||
|
||||
/* 1 for registers not available across function calls.
|
||||
These must include the FIXED_REGISTERS and also any
|
||||
|
@ -642,7 +644,9 @@ extern int ix86_arch;
|
|||
|
||||
#define CALL_USED_REGISTERS \
|
||||
/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg,flags,fpsr, dir*/ \
|
||||
{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
|
||||
{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
/*frame */ \
|
||||
1}
|
||||
|
||||
/* Order in which to allocate registers. Each register must be
|
||||
listed once, even those in FIXED_REGISTERS. List frame pointer
|
||||
|
@ -665,7 +669,9 @@ extern int ix86_arch;
|
|||
|
||||
#define REG_ALLOC_ORDER \
|
||||
/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg,cc,fpsr, dir*/ \
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,17, 18, 19 }
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,17, 18, 19, \
|
||||
/*frame */ \
|
||||
20}
|
||||
|
||||
/* A C statement (sans semicolon) to choose the order in which to
|
||||
allocate hard registers for pseudo-registers local to a basic
|
||||
|
@ -762,7 +768,10 @@ extern int ix86_arch;
|
|||
#define STACK_POINTER_REGNUM 7
|
||||
|
||||
/* Base register for access to local variables of the function. */
|
||||
#define FRAME_POINTER_REGNUM 6
|
||||
#define HARD_FRAME_POINTER_REGNUM 6
|
||||
|
||||
/* Base register for access to local variables of the function. */
|
||||
#define FRAME_POINTER_REGNUM 20
|
||||
|
||||
/* First floating point reg */
|
||||
#define FIRST_FLOAT_REG 8
|
||||
|
@ -853,7 +862,7 @@ enum reg_class
|
|||
AREG, DREG, CREG, BREG, SIREG, DIREG,
|
||||
AD_REGS, /* %eax/%edx for DImode */
|
||||
Q_REGS, /* %eax %ebx %ecx %edx */
|
||||
NON_Q_REGS, /* %esi %edi %ebp %esi */
|
||||
NON_Q_REGS, /* %esi %edi %ebp %esp */
|
||||
INDEX_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp */
|
||||
GENERAL_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp %esp */
|
||||
FP_TOP_REG, FP_SECOND_REG, /* %st(0) %st(1) */
|
||||
|
@ -893,13 +902,13 @@ enum reg_class
|
|||
{0x10}, {0x20}, /* SIREG, DIREG */ \
|
||||
{0x3}, /* AD_REGS */ \
|
||||
{0xf}, /* Q_REGS */ \
|
||||
{0xf0}, /* NON_Q_REGS */ \
|
||||
{0x1100f0}, /* NON_Q_REGS */ \
|
||||
{0x7f}, /* INDEX_REGS */ \
|
||||
{0x100ff}, /* GENERAL_REGS */ \
|
||||
{0x1100ff}, /* GENERAL_REGS */ \
|
||||
{0x0100}, {0x0200}, /* FP_TOP_REG, FP_SECOND_REG */ \
|
||||
{0xff00}, /* FLOAT_REGS */ \
|
||||
{0x1ffff}, /* FLOAT_INT_REGS */ \
|
||||
{0x7ffff} \
|
||||
{0x11ffff}, /* FLOAT_INT_REGS */ \
|
||||
{0x17ffff} \
|
||||
}
|
||||
|
||||
/* The same information, inverted:
|
||||
|
@ -1392,15 +1401,16 @@ do { \
|
|||
followed by "to". Eliminations of the same "from" register are listed
|
||||
in order of preference.
|
||||
|
||||
We have two registers that can be eliminated on the i386. First, the
|
||||
frame pointer register can often be eliminated in favor of the stack
|
||||
pointer register. Secondly, the argument pointer register can always be
|
||||
eliminated; it is replaced with either the stack or frame pointer. */
|
||||
We have three registers that can be eliminated on the i386. First, the
|
||||
hard frame pointer register can often be eliminated in favor of the stack
|
||||
pointer register. Secondly, the argument and frame pointer register can
|
||||
always be eliminated; They are replaced with either the stack or frame pointer. */
|
||||
|
||||
#define ELIMINABLE_REGS \
|
||||
{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
|
||||
{ ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
|
||||
{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
|
||||
#define ELIMINABLE_REGS \
|
||||
{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
|
||||
{ ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
|
||||
{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
|
||||
{ FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} \
|
||||
|
||||
/* Given FROM and TO register numbers, say whether this elimination is allowed.
|
||||
Frame pointer elimination is automatically handled.
|
||||
|
@ -1410,9 +1420,10 @@ do { \
|
|||
|
||||
All other eliminations are valid. */
|
||||
|
||||
#define CAN_ELIMINATE(FROM, TO) \
|
||||
((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM \
|
||||
? ! frame_pointer_needed \
|
||||
#define CAN_ELIMINATE(FROM, TO) \
|
||||
((((FROM) == ARG_POINTER_REGNUM || (FROM) == FRAME_POINTER_REGNUM) \
|
||||
&& (TO) == STACK_POINTER_REGNUM) \
|
||||
? ! frame_pointer_needed \
|
||||
: 1)
|
||||
|
||||
/* Define the offset between two registers, one to be eliminated, and the other
|
||||
|
@ -1444,6 +1455,7 @@ do { \
|
|||
#define REGNO_OK_FOR_BASE_P(REGNO) \
|
||||
((REGNO) <= STACK_POINTER_REGNUM \
|
||||
|| (REGNO) == ARG_POINTER_REGNUM \
|
||||
|| (REGNO) == FRAME_POINTER_REGNUM \
|
||||
|| (unsigned) reg_renumber[REGNO] <= STACK_POINTER_REGNUM)
|
||||
|
||||
#define REGNO_OK_FOR_SIREG_P(REGNO) ((REGNO) == 4 || reg_renumber[REGNO] == 4)
|
||||
|
@ -1471,6 +1483,7 @@ do { \
|
|||
#define REG_OK_FOR_BASE_NONSTRICT_P(X) \
|
||||
(REGNO (X) <= STACK_POINTER_REGNUM \
|
||||
|| REGNO (X) == ARG_POINTER_REGNUM \
|
||||
|| REGNO (X) == FRAME_POINTER_REGNUM \
|
||||
|| REGNO (X) >= FIRST_PSEUDO_REGISTER)
|
||||
|
||||
#define REG_OK_FOR_STRREG_NONSTRICT_P(X) \
|
||||
|
@ -2153,7 +2166,7 @@ while (0)
|
|||
#define HI_REGISTER_NAMES \
|
||||
{"ax","dx","cx","bx","si","di","bp","sp", \
|
||||
"st","st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)","", \
|
||||
"flags","fpsr", "dirflag" }
|
||||
"flags","fpsr", "dirflag", "frame" }
|
||||
|
||||
#define REGISTER_NAMES HI_REGISTER_NAMES
|
||||
|
||||
|
@ -2365,6 +2378,8 @@ do { long l; \
|
|||
{ fputs ("fpsr", FILE); break; } \
|
||||
if (REGNO (X) == ARG_POINTER_REGNUM) \
|
||||
{ fputs ("argp", FILE); break; } \
|
||||
if (REGNO (X) == FRAME_POINTER_REGNUM) \
|
||||
{ fputs ("frame", FILE); break; } \
|
||||
if (STACK_TOP_P (X)) \
|
||||
{ fputs ("st(0)", FILE); break; } \
|
||||
if (FP_REG_P (X)) \
|
||||
|
|
Loading…
Add table
Reference in a new issue