Commit d2a94ec0 by Timothy Moore

*** empty log message ***

From-SVN: r2460
parent 12c83d0b
......@@ -25,3 +25,11 @@
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -DPWB -Dhpux -Dunix -D_HPUX_SOURCE"
/* Link against shared libraries */
#ifdef hpux8
#undef TARGET_DEFAULT
#define TARGET_DEFAULT 8
#undef LINK_SPEC
#define LINK_SPEC "-u main %{g*:-a archive} %{p:-a archive} %{pg:-a archive}"
#endif
......@@ -33,6 +33,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "tree.h"
#include "c-tree.h"
#include "expr.h"
#include "obstack.h"
/* Save the operands last given to a compare for use when we
generate a scc or bcc insn. */
......@@ -204,6 +205,22 @@ fp_reg_operand (op, mode)
{
return reg_renumber && FP_REG_P (op);
}
int
check_fp_mov (operands)
rtx *operands;
{
enum machine_mode mode = GET_MODE (operands[0]);
if (fp_reg_operand (operands[0], mode))
return (register_operand (operands[1], mode)
|| short_memory_operand (operands[1], mode));
else if (fp_reg_operand (operands[1], mode))
return (register_operand (operands[0], mode)
|| short_memory_operand (operands[0], mode));
else
return 1;
}
extern int current_function_uses_pic_offset_table;
extern rtx force_reg (), validize_mem ();
......@@ -481,63 +498,6 @@ initialize_pic ()
void
finalize_pic ()
{
/* The table we use to reference PIC data. */
rtx global_offset_table;
/* Labels to get the PC in the prologue of this function. */
rtx l1, l2;
rtx seq;
int orig_flag_pic = flag_pic;
if (current_function_uses_pic_offset_table == 0)
return;
if (! flag_pic)
abort ();
flag_pic = 0;
l1 = gen_label_rtx ();
l2 = gen_label_rtx ();
start_sequence ();
emit_label (l1);
/* Note that we pun calls and jumps here! */
emit_jump_insn (gen_rtx (PARALLEL, VOIDmode,
gen_rtvec (2,
gen_rtx (SET, VOIDmode, pc_rtx, gen_rtx (LABEL_REF, VOIDmode, l2)),
gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 15), gen_rtx (LABEL_REF, VOIDmode, l2)))));
emit_label (l2);
/* Initialize every time through, since we can't easily
know this to be permanent. */
global_offset_table = gen_rtx (SYMBOL_REF, Pmode, "*__GLOBAL_OFFSET_TABLE_");
pic_pc_rtx = gen_rtx (CONST, Pmode,
gen_rtx (MINUS, Pmode,
global_offset_table,
gen_rtx (CONST, Pmode,
gen_rtx (MINUS, Pmode,
gen_rtx (LABEL_REF, VOIDmode, l1),
pc_rtx))));
emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx,
gen_rtx (HIGH, Pmode, pic_pc_rtx)));
emit_insn (gen_rtx (SET, VOIDmode,
pic_offset_table_rtx,
gen_rtx (LO_SUM, Pmode,
pic_offset_table_rtx, pic_pc_rtx)));
emit_insn (gen_rtx (SET, VOIDmode,
pic_offset_table_rtx,
gen_rtx (PLUS, SImode,
pic_offset_table_rtx, gen_rtx (REG, SImode, 15))));
/* emit_insn (gen_rtx (ASM_INPUT, VOIDmode, "!#PROLOGUE# 1")); */
LABEL_PRESERVE_P (l1) = 1;
LABEL_PRESERVE_P (l2) = 1;
flag_pic = orig_flag_pic;
seq = gen_sequence ();
end_sequence ();
emit_insn_after (seq, get_insns ());
/* Need to emit this whether or not we obey regdecls,
since setjmp/longjmp can cause life info to screw up. */
emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
......@@ -570,15 +530,36 @@ hppa_address_cost (X)
normally. */
int
emit_move_sequence (operands, mode)
emit_move_sequence (operands, mode, scratch_reg)
rtx *operands;
enum machine_mode mode;
rtx scratch_reg;
{
register rtx operand0 = operands[0];
register rtx operand1 = operands[1];
/* Handle most common case first: storing into a register. */
if (register_operand (operand0, mode))
if (fp_reg_operand (operand0, mode)
&& GET_CODE (operand1) == MEM
&& !short_memory_operand (operand1, mode)
&& scratch_reg)
{
emit_move_insn (scratch_reg, XEXP (operand1 , 0));
emit_insn (gen_rtx (SET, VOIDmode, operand0, gen_rtx (MEM, mode,
scratch_reg)));
return 1;
}
else if (fp_reg_operand (operand1, mode)
&& GET_CODE (operand0) == MEM
&& !short_memory_operand (operand0, mode)
&& scratch_reg)
{
emit_move_insn (scratch_reg, XEXP (operand0 , 0));
emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, mode, scratch_reg),
operand1));
return 1;
}
/* Handle most common case: storing into a register. */
else if (register_operand (operand0, mode))
{
if (register_operand (operand1, mode)
|| (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
......@@ -608,21 +589,6 @@ emit_move_sequence (operands, mode)
}
/* Simplify the source if we need to. */
#if 0
if (GET_CODE (operand1) == HIGH
&& symbolic_operand (XEXP (operand1, 0), mode)
&& !read_only_operand (XEXP (operand1, 0)))
{
rtx temp = reload_in_progress ? operand0 : gen_reg_rtx (mode);
emit_insn (gen_rtx (SET, VOIDmode, temp, operand1));
emit_insn (gen_rtx (SET, VOIDmode,
operand0,
gen_rtx (PLUS, mode,
temp, gen_rtx (REG, mode, 27))));
return 1;
}
#endif
if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
{
if (symbolic_operand (operand1, mode))
......@@ -636,12 +602,28 @@ emit_move_sequence (operands, mode)
/* use dp, register 27. */
else if (read_only_operand (operand1))
{
emit_insn (gen_rtx (SET, VOIDmode,
rtx set = gen_rtx (SET, VOIDmode,
operand0,
gen_rtx (HIGH, mode, operand1)));
gen_rtx (LO_SUM, mode, operand0, operand1));
emit_insn (gen_rtx (SET, VOIDmode,
operand0,
gen_rtx (LO_SUM, mode, operand0, operand1)));
gen_rtx (HIGH, mode, operand1)));
if (TARGET_SHARED_LIBS
&& function_label_operand (operand1, mode))
{
rtx temp = reload_in_progress ? scratch_reg
: gen_reg_rtx (mode);
if (!temp)
abort ();
emit_insn (gen_rtx (PARALLEL, VOIDmode,
gen_rtvec (2,
set,
gen_rtx (CLOBBER, VOIDmode,
temp))));
}
else
emit_insn (set);
return 1;
}
else
......@@ -1223,7 +1205,7 @@ char *
output_and (operands)
rtx *operands;
{
if (GET_CODE (operands[2]) == CONST_INT)
if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
{
unsigned mask = INTVAL (operands[2]);
int ls0, ls1, ms0, p, len;
......@@ -1494,6 +1476,7 @@ output_function_prologue (file, size, leaf_function)
{
extern char call_used_regs[];
extern int frame_pointer_needed;
extern int current_function_returns_struct;
int i, offset;
actual_fsize = compute_frame_size (size, leaf_function) + 32;
......@@ -1537,6 +1520,12 @@ output_function_prologue (file, size, leaf_function)
fprintf (file, "\taddil L'%d,30\n\tldo R'%d(1),30\n",
actual_fsize, actual_fsize);
}
/* The hppa calling conventions say that that %r19, the pic offset
register, is saved at sp - 32 (in this function's frame) */
if (flag_pic)
{
fprintf (file, "\tstw %%r19,-32(%%r30)\n");
}
/* Instead of taking one argument, the counter label, as most normal
mcounts do, _mcount appears to behave differently on the HPPA. It
takes the return address of the caller, the address of this
......@@ -1561,6 +1550,8 @@ output_function_prologue (file, size, leaf_function)
: STACK_POINTER_REGNUM;
offsetadj = frame_pointer_needed ? 0 : actual_fsize;
if (current_function_returns_struct)
print_stw (file, STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg);
for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4)
if (regs_ever_live[i])
{
......@@ -1578,6 +1569,8 @@ output_function_prologue (file, size, leaf_function)
for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4)
if (regs_ever_live[i])
print_ldw (file, i, arg_offset, basereg);
if (current_function_returns_struct)
print_ldw (file, STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg);
}
/* Normal register save. */
......@@ -2385,7 +2378,13 @@ secondary_reload_class (class, mode, in)
{
int regno = true_regnum (in);
if (class == SHIFT_REGS && (regno <= 0 || regno >= 32))
if ((TARGET_SHARED_LIBS && function_label_operand (in, mode))
|| ((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
&& ((mode == QImode || mode == HImode || mode == SImode
|| mode == DImode)
&& (class == FP_REGS || class == SNAKE_FP_REGS
|| class == HI_SNAKE_FP_REGS)))
|| (class == SHIFT_REGS && (regno <= 0 || regno >= 32)))
return GENERAL_REGS;
return NO_REGS;
......@@ -2448,3 +2447,31 @@ hppa_builtin_saveregs (arglist)
current_function_internal_arg_pointer,
offset, 0, 0, OPTAB_LIB_WIDEN));
}
extern struct obstack *saveable_obstack;
/* In HPUX 8.0's shared library scheme, special relocations are needed
for function labels if they might be passed to a function
in a shared library (because shared libraries don't live in code
space), and special magic is needed to construct their address. */
void
hppa_encode_label (sym)
rtx sym;
{
char *str = XSTR (sym, 0);
int len = strlen (str);
char *newstr = obstack_alloc (saveable_obstack, len + 2) ;
strcpy (newstr + 1, str);
newstr[0] = '@';
XSTR (sym,0) = newstr;
}
int
function_label_operand (op, mode)
rtx op;
enum machine_mode mode;
{
return GET_CODE (op) == SYMBOL_REF && (XSTR (op, 0))[0] == '@';
}
......@@ -106,6 +106,11 @@ extern int target_flags;
#define TARGET_KERNEL (target_flags & 4)
/* Generate code that will link against HPUX 8.0 shared libraries.
Older linkers and assemblers might not support this. */
#define TARGET_SHARED_LIBS (target_flags & 8)
/* Macro to define tables used to set the flags.
This is a list in braces of pairs in braces,
each pair being { "NAME", VALUE }
......@@ -119,6 +124,8 @@ extern int target_flags;
{"pa-risc-1-1", 1}, \
{"no-bss", 2}, \
{"kernel", 4}, \
{"shared-libs", 8}, \
{"no-shared-libs", -8},\
{ "", TARGET_DEFAULT}}
#define TARGET_DEFAULT 0
......@@ -233,7 +240,8 @@ extern int target_flags;
Reg 3 = Unused
Reg 4 = Frame Pointer (Gnu)
Reg 5-18 = Preserved Registers
Reg 19-22 = Temporary Registers
Reg 19 = Linkage Table Register in HPUX 8.0 shared library scheme.
Reg 20-22 = Temporary Registers
Reg 23-26 = Temporary/Parameter Registers
Reg 27 = Global Data Pointer (hp)
Reg 28 = Temporary/???/Return Value register
......@@ -376,12 +384,20 @@ extern int target_flags;
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
On the HP-PA, the cpu registers can hold any mode. We
force this to be an even register is it cannot hold the full mode. */
#if 0
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
((REGNO) == 0 ? (MODE) == CCmode || (MODE) == CCFPmode \
: (REGNO) < 32 ? ((GET_MODE_SIZE (MODE) <= 4) ? 1 : ((REGNO) & 1) == 0)\
: (REGNO) < 48 ? (GET_MODE_SIZE (MODE) >= 4) \
: (GET_MODE_SIZE (MODE) > 4 ? ((REGNO) & 1) == 0 \
: GET_MODE_SIZE (MODE) == 4))
#endif
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
((REGNO) == 0 ? (MODE) == CCmode || (MODE) == CCFPmode \
: (REGNO) < 32 ? ((GET_MODE_SIZE (MODE) <= 4) ? 1 : ((REGNO) & 1) == 0)\
: (REGNO) < 48 ? (GET_MODE_SIZE (MODE) >= 4) \
: (GET_MODE_SIZE (MODE) > 4 ? ((REGNO) & 1) == 0 \
: 1))
/* Value is 1 if it is a good idea to tie two pseudo registers
when one has mode MODE1 and one has mode MODE2.
......@@ -431,7 +447,7 @@ extern int leaf_function;
/* Register which holds offset table for position-independent
data references. */
#define PIC_OFFSET_TABLE_REGNUM 18
#define PIC_OFFSET_TABLE_REGNUM 19
#define INITIALIZE_PIC initialize_pic ()
#define FINALIZE_PIC finalize_pic ()
......@@ -462,11 +478,14 @@ extern int leaf_function;
/* The HP-PA has four kinds of registers: general regs, 1.0 fp regs,
1.1 fp regs, and the high 1.1 fp regs, to which the operands of
fmpyadd and fmpysub are restricted. */
fmpyadd and fmpysub are restricted.
FP_OR_SNAKE_FP_REGS is for reload_{in,out}di only and isn't used
anywhere else.*/
enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FP_REGS, GENERAL_OR_FP_REGS,
HI_SNAKE_FP_REGS, SNAKE_FP_REGS, GENERAL_OR_SNAKE_FP_REGS,
SHIFT_REGS, ALL_REGS, LIM_REG_CLASSES};
FP_OR_SNAKE_FP_REGS, SHIFT_REGS, ALL_REGS, LIM_REG_CLASSES};
#define N_REG_CLASSES (int) LIM_REG_CLASSES
......@@ -475,7 +494,7 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FP_REGS, GENERAL_OR_FP_REGS,
#define REG_CLASS_NAMES \
{ "NO_REGS", "R1_REGS", "GENERAL_REGS", "FP_REGS", "GENERAL_OR_FP_REGS",\
"HI_SNAKE_FP_REGS", "SNAKE_FP_REGS", "GENERAL_OR_SNAKE_FP_REGS",\
"SHIFT_REGS", "ALL_REGS"}
"FP_OR_SNAKE_FP_REGS","SHIFT_REGS", "ALL_REGS"}
/* Define which registers fit in which classes.
This is an initializer for a vector of HARD_REG_SET
......@@ -491,6 +510,7 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FP_REGS, GENERAL_OR_FP_REGS,
{0, 0, 0xffff0000, 0xffff}, /* HI_SNAKE_FP_REGS */ \
{0, 0xffff0000, ~0, 0xffff}, /* SNAKE_FP_REGS */ \
{-2, 0xffff0000, ~0, 0xffff}, /* GENERAL_OR_SNAKE_FP_REGS */\
{0, ~0, ~0, 0xffff}, /* FP_OR_SNAKE_FP_REGS */\
{0, 0, 0, 0x10000}, /* SHIFT_REGS */ \
{-2, ~0, ~0, 0x1ffff}} /* ALL_REGS */
......@@ -519,7 +539,8 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FP_REGS, GENERAL_OR_FP_REGS,
((C) == 'x' ? (TARGET_SNAKE ? SNAKE_FP_REGS : NO_REGS) : \
((C) == 'y' ? (TARGET_SNAKE ? HI_SNAKE_FP_REGS : NO_REGS) : \
((C) == 'q' ? SHIFT_REGS : \
((C) == 'a' ? R1_REGS : NO_REGS)))))
((C) == 'a' ? R1_REGS : \
((C) == 'z' ? FP_OR_SNAKE_FP_REGS : NO_REGS))))))
/* The letters I, J, K, L and M in a register constraint string
can be used to stand for particular ranges of immediate operands.
......@@ -794,6 +815,13 @@ extern enum cmp_type hppa_branch_type;
do { fprintf (FILE, ",ARGW%d=FU", (ARG0)); \
fprintf (FILE, ",ARGW%d=FR", (ARG1));} while (0)
#endif
#ifdef BUGGY_GAS
#define EXPORT_PARMS(FILE) fputs (",PRIV_LEV=3", FILE)
#else
#define EXPORT_PARMS(FILE) fputs (",ENTRY,PRIV_LEV=3", FILE)
#endif
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
do { tree fntype = DECL_RESULT (DECL); \
tree tree_type = TREE_TYPE (DECL); \
......@@ -802,7 +830,7 @@ extern enum cmp_type hppa_branch_type;
if (TREE_PUBLIC (DECL)) \
{ extern int current_function_varargs; \
fputs ("\t.EXPORT ", FILE); assemble_name (FILE, NAME); \
fputs (",PRIV_LEV=3", FILE); \
EXPORT_PARMS (FILE); \
for (parm = DECL_ARGUMENTS (DECL), i = 0; parm && i < 4; \
parm = TREE_CHAIN (parm)) \
{ \
......@@ -984,8 +1012,8 @@ extern union tree_node *current_function_decl;
#define REGNO_OK_FOR_BASE_P(REGNO) \
((REGNO) && ((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32))
#define REGNO_OK_FOR_FP_P(REGNO) \
(((REGNO) >= 32 || reg_renumber[REGNO] >= 32)\
&& ((REGNO) <= 111 || reg_renumber[REGNO] <= 111))
(((REGNO) >= 32 && (REGNO) <= 111)\
|| (reg_renumber[REGNO] >= 32 && reg_renumber[REGNO] <= 111))
/* Now macros that check whether X is a register and also,
strictly, whether it is in a specified class.
......@@ -1200,7 +1228,7 @@ extern union tree_node *current_function_decl;
if (memory_address_p (MODE, X)) \
goto WIN; \
if (flag_pic) (X) = legitimize_pic_address (X, MODE, gen_reg_rtx (Pmode));\
else if ((GET_CODE (X) == SYMBOL_REF && read_only_operand (X))\
else if ((GET_CODE (X) == SYMBOL_REF & read_only_operand (X)) \
|| GET_CODE (X) == LABEL_REF) \
(X) = gen_rtx (LO_SUM, Pmode, \
copy_to_mode_reg (Pmode, gen_rtx (HIGH, Pmode, X)), X); \
......@@ -1246,7 +1274,10 @@ extern union tree_node *current_function_decl;
do \
{ \
if (TREE_CODE (DECL) == FUNCTION_DECL) \
SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \
{ \
hppa_encode_label (XEXP (DECL_RTL (DECL), 0)); \
SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \
} \
else \
{ \
rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
......@@ -1376,7 +1407,7 @@ while (0)
case MOD: \
case UMOD: \
return COSTS_N_INSNS (60); \
case PLUS: /* this includes shNadd insns */ \
case PLUS: /* this includes shNadd insns */ \
return COSTS_N_INSNS (1) + 2;
/* Conditional branches with empty delay slots have a length of two. */
......@@ -1518,7 +1549,7 @@ bss_section () \
`assemble_name' uses this. */
#define ASM_OUTPUT_LABELREF(FILE,NAME) \
fprintf (FILE, "%s", NAME)
fprintf ((FILE), "%s", (NAME) + ((NAME)[0] == '@' ? 1 : 0))
/* This is how to output an internal numbered label where
PREFIX is the class of label and NUM is the number within the class. */
......@@ -1578,6 +1609,7 @@ bss_section () \
#define ASM_OUTPUT_ASCII(FILE, P, SIZE) \
output_ascii ((FILE), (P), (SIZE))
#if 0
#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
fprintf (FILE, "\tstws,mb %s,4(0,30)\n", reg_names[REGNO])
......@@ -1586,7 +1618,10 @@ bss_section () \
#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
fprintf (FILE, "\tldws,ma -4(0,30),%s\n", reg_names[REGNO])
#endif
#define ASM_OUTPUT_REG_PUSH(FILE,REGNO)
#define ASM_OUTPUT_REG_POP(FILE,REGNO)
/* This is how to output an element of a case-vector that is absolute.
Note that this method makes filling these branch delay slots
virtually impossible. */
......@@ -1732,3 +1767,4 @@ extern void output_global_address ();
extern struct rtx_def *legitimize_pic_address ();
extern struct rtx_def *gen_cmp_fp ();
extern struct rtx_def *gen_scond_fp ();
extern void hppa_encode_label ();
......@@ -23,6 +23,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <magic.h>
#if defined(SHL_MAGIC)
#define hpux8 1
#define HAVE_VPRINTF
#endif
#define USG
......
#if __GNUC__ > 1
/* Define __gnuc_va_list. */
......@@ -11,12 +10,23 @@ typedef double *__gnuc_va_list;
/* If this is for internal libc use, don't define anything but
__gnuc_va_list. */
#if defined (_STDARG_H) || defined (_VARARGS_H)
#if __GNUC__ > 1
#define __va_ellipsis ...
#define __gnuc_va_start(AP) ((AP) = (va_list)__builtin_saveregs())
#else
#define va_alist __va_a__, __va_b__, __va_c__, __va_d__
#define __va_ellipsis
#define __gnuc_va_start(AP)\
(AP) = (double *) &__va_a__, &__va_b__, &__va_c__, &__va_d__, \
(AP) = (double *)((char *)(AP) + 4)
#endif /* __GNUC__ > 1 */
#ifdef _STDARG_H
#define va_start(AP,LASTARG) ((AP) = (va_list)__builtin_saveregs())
#define va_start(AP,LASTARG) __gnuc_va_start (AP)
#else
/* The ... causes current_function_varargs to be set in cc1. */
#define va_dcl long va_alist; ...
#define va_start(AP) ((AP) = (va_list)__builtin_saveregs())
#define va_dcl long va_alist; __va_ellipsis
#define va_start(AP) __gnuc_va_start (AP)
#endif
#define va_arg(AP,TYPE) \
......@@ -31,8 +41,3 @@ typedef double *__gnuc_va_list;
#define va_end(AP)
#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
#else /* not __GNUC__ > 1 */
#include "/usr/local/lib/gcc-include/va-hp9k8.h"
#define _VA_LIST_
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment