pdp11-protos.h (pdp11_initial_elimination_offset, [...]): New functions.
* config/pdp11/pdp11-protos.h (pdp11_initial_elimination_offset, pdp11_regno_reg_class): New functions. * config/pdp11/pdp11.md (define_constants): Add register numbers. * config/pdp11/pdp11.c (pdp11_regno_reg_class, pdp11_sp_frame_offset, pdp11_initial_elimination_offset): New functions. * config/pdp11/pdp11.h (FIXED_REGISTERS, CALL_USED_REGISTERS): Add frame pointer and argument pointer pseudo-registers. (ARG_POINTER_REGNUM): Define. (REG_CLASS_CONTENTS, REGNO_REG_CLASS): Add frame pointer and argument pointer. (FIRST_PARM_OFFSET): Update for argument pointer. (INITIAL_FRAME_POINTER_OFFSET): Delete. (ELIMINABLE_REGS, INITIAL_ELIMINATION_OFFSET): New macros. (REGNO_OK_FOR_BASE_P, REGNO_OK_FOR_INDEX_P, REGISTER_NAMES): Add frame pointer and argument pointer. From-SVN: r166978
This commit is contained in:
parent
a9aa2c3ae2
commit
58dd8e861c
|
@ -1,3 +1,22 @@
|
||||||
|
2010-11-20 Paul Koning <ni1d@arrl.net>
|
||||||
|
|
||||||
|
* config/pdp11/pdp11-protos.h (pdp11_initial_elimination_offset,
|
||||||
|
pdp11_regno_reg_class): New functions.
|
||||||
|
* config/pdp11/pdp11.md (define_constants): Add register numbers.
|
||||||
|
* config/pdp11/pdp11.c (pdp11_regno_reg_class,
|
||||||
|
pdp11_sp_frame_offset, pdp11_initial_elimination_offset): New
|
||||||
|
functions.
|
||||||
|
* config/pdp11/pdp11.h (FIXED_REGISTERS, CALL_USED_REGISTERS): Add
|
||||||
|
frame pointer and argument pointer pseudo-registers.
|
||||||
|
(ARG_POINTER_REGNUM): Define.
|
||||||
|
(REG_CLASS_CONTENTS, REGNO_REG_CLASS): Add frame pointer and
|
||||||
|
argument pointer.
|
||||||
|
(FIRST_PARM_OFFSET): Update for argument pointer.
|
||||||
|
(INITIAL_FRAME_POINTER_OFFSET): Delete.
|
||||||
|
(ELIMINABLE_REGS, INITIAL_ELIMINATION_OFFSET): New macros.
|
||||||
|
(REGNO_OK_FOR_BASE_P, REGNO_OK_FOR_INDEX_P, REGISTER_NAMES): Add
|
||||||
|
frame pointer and argument pointer.
|
||||||
|
|
||||||
2010-11-20 Jakub Jelinek <jakub@redhat.com>
|
2010-11-20 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR debug/46561
|
PR debug/46561
|
||||||
|
|
|
@ -35,6 +35,8 @@ extern bool pdp11_cannot_change_mode_class (enum machine_mode,
|
||||||
enum machine_mode, enum reg_class);
|
enum machine_mode, enum reg_class);
|
||||||
extern bool pdp11_secondary_memory_needed (reg_class_t, reg_class_t,
|
extern bool pdp11_secondary_memory_needed (reg_class_t, reg_class_t,
|
||||||
enum machine_mode);
|
enum machine_mode);
|
||||||
|
extern int pdp11_initial_elimination_offset (int, int);
|
||||||
|
extern enum reg_class pdp11_regno_reg_class (int);
|
||||||
|
|
||||||
#endif /* RTX_CODE */
|
#endif /* RTX_CODE */
|
||||||
|
|
||||||
|
|
|
@ -300,7 +300,7 @@ pdp11_output_function_prologue (FILE *stream, HOST_WIDE_INT size)
|
||||||
asm_fprintf (stream, "\tsub $%#wo, sp\n", fsize);
|
asm_fprintf (stream, "\tsub $%#wo, sp\n", fsize);
|
||||||
|
|
||||||
/* save CPU registers */
|
/* save CPU registers */
|
||||||
for (regno = 0; regno <= PC_REGNUM; regno++)
|
for (regno = R0_REGNUM; regno <= PC_REGNUM; regno++)
|
||||||
if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
|
if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
|
||||||
if (! ((regno == FRAME_POINTER_REGNUM)
|
if (! ((regno == FRAME_POINTER_REGNUM)
|
||||||
&& frame_pointer_needed))
|
&& frame_pointer_needed))
|
||||||
|
@ -379,7 +379,7 @@ pdp11_output_function_epilogue (FILE *stream, HOST_WIDE_INT size)
|
||||||
k = 2*j;
|
k = 2*j;
|
||||||
|
|
||||||
/* change fp -> r5 due to the compile error on libgcc2.c */
|
/* change fp -> r5 due to the compile error on libgcc2.c */
|
||||||
for (i = PC_REGNUM ; i >= 0 ; i--)
|
for (i = PC_REGNUM ; i >= R0_REGNUM ; i--)
|
||||||
if (df_regs_ever_live_p (i) && ! call_used_regs[i])
|
if (df_regs_ever_live_p (i) && ! call_used_regs[i])
|
||||||
fprintf(stream, "\tmov %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
|
fprintf(stream, "\tmov %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
|
||||||
(-fsize-2*j--)&0xffff, reg_names[i]);
|
(-fsize-2*j--)&0xffff, reg_names[i]);
|
||||||
|
@ -1706,6 +1706,71 @@ pdp11_secondary_memory_needed (reg_class_t c1, reg_class_t c2,
|
||||||
return (fromfloat != tofloat);
|
return (fromfloat != tofloat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the class number of the smallest class containing
|
||||||
|
reg number REGNO. */
|
||||||
|
enum reg_class
|
||||||
|
pdp11_regno_reg_class (int regno)
|
||||||
|
{
|
||||||
|
if (regno == FRAME_POINTER_REGNUM || regno == ARG_POINTER_REGNUM)
|
||||||
|
return GENERAL_REGS;
|
||||||
|
else if (regno > AC3_REGNUM)
|
||||||
|
return NO_LOAD_FPU_REGS;
|
||||||
|
else if (regno >= AC0_REGNUM)
|
||||||
|
return LOAD_FPU_REGS;
|
||||||
|
else if (regno & 1)
|
||||||
|
return MUL_REGS;
|
||||||
|
else
|
||||||
|
return GENERAL_REGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
pdp11_sp_frame_offset (void)
|
||||||
|
{
|
||||||
|
int offset = 0, regno;
|
||||||
|
offset = get_frame_size();
|
||||||
|
for (regno = 0; regno <= PC_REGNUM; regno++)
|
||||||
|
if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
|
||||||
|
offset += 2;
|
||||||
|
for (regno = AC0_REGNUM; regno <= AC5_REGNUM; regno++)
|
||||||
|
if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
|
||||||
|
offset += 8;
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the offset between two registers, one to be eliminated, and the other
|
||||||
|
its replacement, at the start of a routine. */
|
||||||
|
|
||||||
|
int
|
||||||
|
pdp11_initial_elimination_offset (int from, int to)
|
||||||
|
{
|
||||||
|
int spoff;
|
||||||
|
|
||||||
|
if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
|
||||||
|
return 4;
|
||||||
|
else if (from == FRAME_POINTER_REGNUM
|
||||||
|
&& to == HARD_FRAME_POINTER_REGNUM)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gcc_assert (to == STACK_POINTER_REGNUM);
|
||||||
|
|
||||||
|
/* Get the size of the register save area. */
|
||||||
|
spoff = pdp11_sp_frame_offset ();
|
||||||
|
if (from == FRAME_POINTER_REGNUM)
|
||||||
|
return spoff;
|
||||||
|
|
||||||
|
gcc_assert (from == ARG_POINTER_REGNUM);
|
||||||
|
|
||||||
|
/* If there is a frame pointer, that is saved too. */
|
||||||
|
if (frame_pointer_needed)
|
||||||
|
spoff += 2;
|
||||||
|
|
||||||
|
/* Account for the saved PC in the function call. */
|
||||||
|
return spoff + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* A copy of output_addr_const modified for pdp11 expression syntax.
|
/* A copy of output_addr_const modified for pdp11 expression syntax.
|
||||||
output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
|
output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
|
||||||
|
|
|
@ -149,11 +149,9 @@ extern const struct real_format pdp11_d_format;
|
||||||
reg 5 = fp; not necessarily!
|
reg 5 = fp; not necessarily!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* don't let them touch fp regs for the time being !*/
|
|
||||||
|
|
||||||
#define FIXED_REGISTERS \
|
#define FIXED_REGISTERS \
|
||||||
{0, 0, 0, 0, 0, 0, 1, 1, \
|
{0, 0, 0, 0, 0, 0, 1, 1, \
|
||||||
0, 0, 0, 0, 0, 0 }
|
0, 0, 0, 0, 0, 0, 1, 1 }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -167,7 +165,7 @@ extern const struct real_format pdp11_d_format;
|
||||||
/* don't know about fp */
|
/* don't know about fp */
|
||||||
#define CALL_USED_REGISTERS \
|
#define CALL_USED_REGISTERS \
|
||||||
{1, 1, 0, 0, 0, 0, 1, 1, \
|
{1, 1, 0, 0, 0, 0, 1, 1, \
|
||||||
0, 0, 0, 0, 0, 0 }
|
0, 0, 0, 0, 0, 0, 1, 1 }
|
||||||
|
|
||||||
|
|
||||||
/* Make sure everything's fine if we *don't* have an FPU.
|
/* Make sure everything's fine if we *don't* have an FPU.
|
||||||
|
@ -183,7 +181,7 @@ extern const struct real_format pdp11_d_format;
|
||||||
if (!TARGET_FPU) \
|
if (!TARGET_FPU) \
|
||||||
{ \
|
{ \
|
||||||
COPY_HARD_REG_SET (x, reg_class_contents[(int)FPU_REGS]); \
|
COPY_HARD_REG_SET (x, reg_class_contents[(int)FPU_REGS]); \
|
||||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++ ) \
|
for (i = R0_REGNUM; i < FIRST_PSEUDO_REGISTER; i++ ) \
|
||||||
if (TEST_HARD_REG_BIT (x, i)) \
|
if (TEST_HARD_REG_BIT (x, i)) \
|
||||||
fixed_regs[i] = call_used_regs[i] = 1; \
|
fixed_regs[i] = call_used_regs[i] = 1; \
|
||||||
} \
|
} \
|
||||||
|
@ -239,9 +237,6 @@ extern const struct real_format pdp11_d_format;
|
||||||
/* Specify the registers used for certain standard purposes.
|
/* Specify the registers used for certain standard purposes.
|
||||||
The values of these macros are register numbers. */
|
The values of these macros are register numbers. */
|
||||||
|
|
||||||
/* Base register for access to arguments of the function. */
|
|
||||||
#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM
|
|
||||||
|
|
||||||
/* Register in which static-chain is passed to a function. */
|
/* Register in which static-chain is passed to a function. */
|
||||||
/* ??? - i don't want to give up a reg for this! */
|
/* ??? - i don't want to give up a reg for this! */
|
||||||
#define STATIC_CHAIN_REGNUM 4
|
#define STATIC_CHAIN_REGNUM 4
|
||||||
|
@ -298,19 +293,14 @@ enum reg_class { NO_REGS, MUL_REGS, GENERAL_REGS, LOAD_FPU_REGS, NO_LOAD_FPU_REG
|
||||||
This is an initializer for a vector of HARD_REG_SET
|
This is an initializer for a vector of HARD_REG_SET
|
||||||
of length N_REG_CLASSES. */
|
of length N_REG_CLASSES. */
|
||||||
|
|
||||||
#define REG_CLASS_CONTENTS {{0}, {0x00aa}, {0x00ff}, {0x0f00}, {0x3000}, {0x3f00}, {0x3fff}}
|
#define REG_CLASS_CONTENTS {{0}, {0x00aa}, {0xc0ff}, {0x0f00}, {0x3000}, {0x3f00}, {0xffff}}
|
||||||
|
|
||||||
/* The same information, inverted:
|
/* The same information, inverted:
|
||||||
Return the class number of the smallest class containing
|
Return the class number of the smallest class containing
|
||||||
reg number REGNO. This could be a conditional expression
|
reg number REGNO. This could be a conditional expression
|
||||||
or could index an array. */
|
or could index an array. */
|
||||||
|
|
||||||
#define REGNO_REG_CLASS(REGNO) \
|
#define REGNO_REG_CLASS(REGNO) pdp11_regno_reg_class (REGNO)
|
||||||
((REGNO) >= AC0_REGNUM ? \
|
|
||||||
((REGNO) <= AC3_REGNUM ? LOAD_FPU_REGS : \
|
|
||||||
NO_LOAD_FPU_REGS) : \
|
|
||||||
(((REGNO) & 1) ? MUL_REGS : GENERAL_REGS))
|
|
||||||
|
|
||||||
|
|
||||||
/* The class value for index registers, and the one for base regs. */
|
/* The class value for index registers, and the one for base regs. */
|
||||||
#define INDEX_REG_CLASS GENERAL_REGS
|
#define INDEX_REG_CLASS GENERAL_REGS
|
||||||
|
@ -369,13 +359,8 @@ enum reg_class { NO_REGS, MUL_REGS, GENERAL_REGS, LOAD_FPU_REGS, NO_LOAD_FPU_REG
|
||||||
stack */
|
stack */
|
||||||
extern int current_first_parm_offset;
|
extern int current_first_parm_offset;
|
||||||
|
|
||||||
/* Offset of first parameter from the argument pointer register value.
|
/* Offset of first parameter from the argument pointer register value. */
|
||||||
For the pdp11, this is nonzero to account for the return address.
|
#define FIRST_PARM_OFFSET(FNDECL) 0
|
||||||
1 - return address
|
|
||||||
2 - frame pointer, if needed
|
|
||||||
|
|
||||||
*/
|
|
||||||
#define FIRST_PARM_OFFSET(FNDECL) ((frame_pointer_needed) ? 4 : 2)
|
|
||||||
|
|
||||||
/* Define how to find the value returned by a function.
|
/* Define how to find the value returned by a function.
|
||||||
VALTYPE is the data type of the value (as a tree).
|
VALTYPE is the data type of the value (as a tree).
|
||||||
|
@ -425,19 +410,27 @@ extern int may_call_alloca;
|
||||||
|
|
||||||
#define EXIT_IGNORE_STACK 1
|
#define EXIT_IGNORE_STACK 1
|
||||||
|
|
||||||
#define INITIAL_FRAME_POINTER_OFFSET(DEPTH_VAR) \
|
/* Definitions for register eliminations.
|
||||||
{ \
|
|
||||||
int offset, regno; \
|
This is an array of structures. Each structure initializes one pair
|
||||||
offset = get_frame_size(); \
|
of eliminable registers. The "from" register number is given first,
|
||||||
for (regno = 0; regno <= PC_REGNUM; regno++) \
|
followed by "to". Eliminations of the same "from" register are listed
|
||||||
if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]) \
|
in order of preference.
|
||||||
offset += 2; \
|
|
||||||
for (regno = AC0_REGNUM; regno <= AC5_REGNUM; regno++) \
|
There are two registers that can always be eliminated on the pdp11.
|
||||||
if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]) \
|
The frame pointer and the arg pointer can be replaced by either the
|
||||||
offset += 8; \
|
hard frame pointer or to the stack pointer, depending upon the
|
||||||
/* offset -= 2; no fp on stack frame */ \
|
circumstances. The hard frame pointer is not used before reload and
|
||||||
(DEPTH_VAR) = offset; \
|
so it is not eligible for elimination. */
|
||||||
}
|
|
||||||
|
#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}} \
|
||||||
|
|
||||||
|
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
|
||||||
|
((OFFSET) = pdp11_initial_elimination_offset ((FROM), (TO)))
|
||||||
|
|
||||||
|
|
||||||
/* Addressing modes, and classification of registers for them. */
|
/* Addressing modes, and classification of registers for them. */
|
||||||
|
@ -454,10 +447,11 @@ extern int may_call_alloca;
|
||||||
Since they use reg_renumber, they are safe only once reg_renumber
|
Since they use reg_renumber, they are safe only once reg_renumber
|
||||||
has been allocated, which happens in local-alloc.c. */
|
has been allocated, which happens in local-alloc.c. */
|
||||||
|
|
||||||
#define REGNO_OK_FOR_INDEX_P(REGNO) \
|
|
||||||
((REGNO) <= PC_REGNUM || (unsigned) reg_renumber[REGNO] <= PC_REGNUM)
|
|
||||||
#define REGNO_OK_FOR_BASE_P(REGNO) \
|
#define REGNO_OK_FOR_BASE_P(REGNO) \
|
||||||
((REGNO) <= PC_REGNUM || (unsigned) reg_renumber[REGNO] <= PC_REGNUM)
|
((REGNO) <= PC_REGNUM || (unsigned) reg_renumber[REGNO] <= PC_REGNUM || \
|
||||||
|
(REGNO) == ARG_POINTER_REGNUM || (REGNO) == FRAME_POINTER_REGNUM)
|
||||||
|
|
||||||
|
#define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P (REGNO)
|
||||||
|
|
||||||
/* Now macros that check whether X is a register and also,
|
/* Now macros that check whether X is a register and also,
|
||||||
strictly, whether it is in a specified class.
|
strictly, whether it is in a specified class.
|
||||||
|
@ -743,7 +737,7 @@ extern struct rtx_def *cc0_reg_rtx;
|
||||||
|
|
||||||
#define REGISTER_NAMES \
|
#define REGISTER_NAMES \
|
||||||
{"r0", "r1", "r2", "r3", "r4", "r5", "sp", "pc", \
|
{"r0", "r1", "r2", "r3", "r4", "r5", "sp", "pc", \
|
||||||
"ac0", "ac1", "ac2", "ac3", "ac4", "ac5" }
|
"ac0", "ac1", "ac2", "ac3", "ac4", "ac5", "fp", "ap" }
|
||||||
|
|
||||||
/* Globalizing directive for a label. */
|
/* Globalizing directive for a label. */
|
||||||
#define GLOBAL_ASM_OP "\t.globl "
|
#define GLOBAL_ASM_OP "\t.globl "
|
||||||
|
|
|
@ -25,15 +25,20 @@
|
||||||
(define_constants
|
(define_constants
|
||||||
[
|
[
|
||||||
;; Register numbers
|
;; Register numbers
|
||||||
|
(R0_REGNUM 0)
|
||||||
(RETVAL_REGNUM 0)
|
(RETVAL_REGNUM 0)
|
||||||
(FRAME_POINTER_REGNUM 5)
|
(HARD_FRAME_POINTER_REGNUM 5)
|
||||||
(STACK_POINTER_REGNUM 6)
|
(STACK_POINTER_REGNUM 6)
|
||||||
(PC_REGNUM 7)
|
(PC_REGNUM 7)
|
||||||
(AC0_REGNUM 8)
|
(AC0_REGNUM 8)
|
||||||
(AC3_REGNUM 11)
|
(AC3_REGNUM 11)
|
||||||
(AC4_REGNUM 12)
|
(AC4_REGNUM 12)
|
||||||
(AC5_REGNUM 13)
|
(AC5_REGNUM 13)
|
||||||
(FIRST_PSEUDO_REGISTER 14)
|
;; The next two are not physical registers but are used for addressing
|
||||||
|
;; arguments.
|
||||||
|
(FRAME_POINTER_REGNUM 14)
|
||||||
|
(ARG_POINTER_REGNUM 15)
|
||||||
|
(FIRST_PSEUDO_REGISTER 16)
|
||||||
;; Branch offset limits, as byte offsets from instruction address
|
;; Branch offset limits, as byte offsets from instruction address
|
||||||
(MIN_BRANCH -254)
|
(MIN_BRANCH -254)
|
||||||
(MAX_BRANCH 256)
|
(MAX_BRANCH 256)
|
||||||
|
|
Loading…
Reference in New Issue