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:
Paul Koning 2010-11-20 14:11:32 -05:00 committed by Paul Koning
parent a9aa2c3ae2
commit 58dd8e861c
5 changed files with 129 additions and 44 deletions

View File

@ -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>
PR debug/46561

View File

@ -35,6 +35,8 @@ extern bool pdp11_cannot_change_mode_class (enum machine_mode,
enum machine_mode, enum reg_class);
extern bool pdp11_secondary_memory_needed (reg_class_t, reg_class_t,
enum machine_mode);
extern int pdp11_initial_elimination_offset (int, int);
extern enum reg_class pdp11_regno_reg_class (int);
#endif /* RTX_CODE */

View File

@ -300,7 +300,7 @@ pdp11_output_function_prologue (FILE *stream, HOST_WIDE_INT size)
asm_fprintf (stream, "\tsub $%#wo, sp\n", fsize);
/* 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 (! ((regno == FRAME_POINTER_REGNUM)
&& frame_pointer_needed))
@ -379,7 +379,7 @@ pdp11_output_function_epilogue (FILE *stream, HOST_WIDE_INT size)
k = 2*j;
/* 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])
fprintf(stream, "\tmov %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
(-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 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.
output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't

View File

@ -149,11 +149,9 @@ extern const struct real_format pdp11_d_format;
reg 5 = fp; not necessarily!
*/
/* don't let them touch fp regs for the time being !*/
#define FIXED_REGISTERS \
{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 */
#define CALL_USED_REGISTERS \
{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.
@ -183,7 +181,7 @@ extern const struct real_format pdp11_d_format;
if (!TARGET_FPU) \
{ \
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)) \
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.
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. */
/* ??? - i don't want to give up a reg for this! */
#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
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:
Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression
or could index an array. */
#define REGNO_REG_CLASS(REGNO) \
((REGNO) >= AC0_REGNUM ? \
((REGNO) <= AC3_REGNUM ? LOAD_FPU_REGS : \
NO_LOAD_FPU_REGS) : \
(((REGNO) & 1) ? MUL_REGS : GENERAL_REGS))
#define REGNO_REG_CLASS(REGNO) pdp11_regno_reg_class (REGNO)
/* The class value for index registers, and the one for base 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 */
extern int current_first_parm_offset;
/* Offset of first parameter from the argument pointer register value.
For the pdp11, this is nonzero to account for the return address.
1 - return address
2 - frame pointer, if needed
*/
#define FIRST_PARM_OFFSET(FNDECL) ((frame_pointer_needed) ? 4 : 2)
/* Offset of first parameter from the argument pointer register value. */
#define FIRST_PARM_OFFSET(FNDECL) 0
/* Define how to find the value returned by a function.
VALTYPE is the data type of the value (as a tree).
@ -425,20 +410,28 @@ extern int may_call_alloca;
#define EXIT_IGNORE_STACK 1
#define INITIAL_FRAME_POINTER_OFFSET(DEPTH_VAR) \
{ \
int offset, 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; \
/* offset -= 2; no fp on stack frame */ \
(DEPTH_VAR) = offset; \
}
/* Definitions for register eliminations.
This is an array of structures. Each structure initializes one pair
of eliminable registers. The "from" register number is given first,
followed by "to". Eliminations of the same "from" register are listed
in order of preference.
There are two registers that can always be eliminated on the pdp11.
The frame pointer and the arg pointer can be replaced by either the
hard frame pointer or to the stack pointer, depending upon the
circumstances. The hard frame pointer is not used before reload and
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. */
@ -454,10 +447,11 @@ extern int may_call_alloca;
Since they use reg_renumber, they are safe only once reg_renumber
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) \
((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,
strictly, whether it is in a specified class.
@ -743,7 +737,7 @@ extern struct rtx_def *cc0_reg_rtx;
#define REGISTER_NAMES \
{"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. */
#define GLOBAL_ASM_OP "\t.globl "

View File

@ -25,15 +25,20 @@
(define_constants
[
;; Register numbers
(R0_REGNUM 0)
(RETVAL_REGNUM 0)
(FRAME_POINTER_REGNUM 5)
(HARD_FRAME_POINTER_REGNUM 5)
(STACK_POINTER_REGNUM 6)
(PC_REGNUM 7)
(AC0_REGNUM 8)
(AC3_REGNUM 11)
(AC4_REGNUM 12)
(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
(MIN_BRANCH -254)
(MAX_BRANCH 256)