From e621b5885a6108a671b093bcb4770e5020e92f4a Mon Sep 17 00:00:00 2001 From: Paul Koning Date: Tue, 3 Feb 2004 17:36:02 +0000 Subject: [PATCH] pdp11-modes.def: Add RESET_FLOAT_FORMAT calls. * config/pdp11/pdp11-modes.def: Add RESET_FLOAT_FORMAT calls. * config/pdp11/pdp11-protos.h (legitimate_const_double_p): Add. * config/pdp11/pdp11.c (encode_pdp11_f, decode_pdp11_f, encode_pdp11_d, decode_pdp11_d): New functions to handle PDP11 floating point format. (pdp11_f_format, pdp11_d_format): New real_format descriptors for the above functions. (output_move_quad): Output float values in correct target format. (legitimate_const_double_p): New function. * config/pdp11/pdp11.h: Fix typos. (FLOAT_WORDS_BIG_ENDIAN): Add definition. (TARGET_FLOAT_FORMAT): Ditto. (pdp11_f_format, pdp11_d_format): Add external declarations. (MAX_REGS_PER_ADDRESS): Corrected. (LEGITIMATE_CONSTANT_P): Use legitimate_const_double_p(). (PRINT_OPERAND): Output float literals in target format. From-SVN: r77180 --- gcc/ChangeLog | 19 +++++ gcc/config/pdp11/pdp11-modes.def | 4 +- gcc/config/pdp11/pdp11-protos.h | 3 +- gcc/config/pdp11/pdp11.c | 121 +++++++++++++++++++++++++++---- gcc/config/pdp11/pdp11.h | 32 ++++++-- 5 files changed, 153 insertions(+), 26 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eedaab5d58d..3e2cfe90604 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2004-02-03 Paul Koning + + * config/pdp11/pdp11-modes.def: Add RESET_FLOAT_FORMAT calls. + * config/pdp11/pdp11-protos.h (legitimate_const_double_p): Add. + * config/pdp11/pdp11.c (encode_pdp11_f, decode_pdp11_f, + encode_pdp11_d, decode_pdp11_d): New functions to handle PDP11 + floating point format. + (pdp11_f_format, pdp11_d_format): New real_format descriptors for + the above functions. + (output_move_quad): Output float values in correct target format. + (legitimate_const_double_p): New function. + * config/pdp11/pdp11.h: Fix typos. + (FLOAT_WORDS_BIG_ENDIAN): Add definition. + (TARGET_FLOAT_FORMAT): Ditto. + (pdp11_f_format, pdp11_d_format): Add external declarations. + (MAX_REGS_PER_ADDRESS): Corrected. + (LEGITIMATE_CONSTANT_P): Use legitimate_const_double_p(). + (PRINT_OPERAND): Output float literals in target format. + 2004-02-03 Mark Mitchell PR c++/13975 diff --git a/gcc/config/pdp11/pdp11-modes.def b/gcc/config/pdp11/pdp11-modes.def index da083ad24a8..fdc1540b729 100644 --- a/gcc/config/pdp11/pdp11-modes.def +++ b/gcc/config/pdp11/pdp11-modes.def @@ -1,5 +1,5 @@ /* Definitions of target machine for GNU compiler, for the pdp-11 - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2004 Free Software Foundation, Inc. Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at). This file is part of GCC. @@ -23,3 +23,5 @@ Boston, MA 02111-1307, USA. */ CCFPmode is used for FPU, but should we use a separate reg? */ CC_MODE (CCFP); +RESET_FLOAT_FORMAT (SF, pdp11_f_format); +RESET_FLOAT_FORMAT (DF, pdp11_d_format); diff --git a/gcc/config/pdp11/pdp11-protos.h b/gcc/config/pdp11/pdp11-protos.h index 2aebab01dc5..4c460affb58 100644 --- a/gcc/config/pdp11/pdp11-protos.h +++ b/gcc/config/pdp11/pdp11-protos.h @@ -1,5 +1,5 @@ /* Definitions of target machine for GNU compiler, for the pdp-11 - Copyright (C) 2000, 2003 Free Software Foundation, Inc. + Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc. Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at). This file is part of GCC. @@ -29,6 +29,7 @@ extern int simple_memory_operand (rtx, enum machine_mode); extern int comp_operator (rtx, enum machine_mode); extern int legitimate_address_p (enum machine_mode, rtx); +extern int legitimate_const_double_p (rtx); extern void notice_update_cc_on_set (rtx, rtx); extern void output_addr_const_pdp11 (FILE *, rtx); extern const char *output_move_double (rtx *); diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c index 1b438d68970..9102dcdd3a0 100644 --- a/gcc/config/pdp11/pdp11.c +++ b/gcc/config/pdp11/pdp11.c @@ -51,6 +51,90 @@ Boston, MA 02111-1307, USA. */ defined in tm.h */ int current_first_parm_offset; +/* Routines to encode/decode pdp11 floats */ +static void encode_pdp11_f (const struct real_format *fmt, + long *, const REAL_VALUE_TYPE *); +static void decode_pdp11_f (const struct real_format *, + REAL_VALUE_TYPE *, const long *); +static void encode_pdp11_d (const struct real_format *fmt, + long *, const REAL_VALUE_TYPE *); +static void decode_pdp11_d (const struct real_format *, + REAL_VALUE_TYPE *, const long *); + +/* These two are taken from the corresponding vax descriptors + in real.c, changing only the encode/decode routine pointers. */ +const struct real_format pdp11_f_format = + { + encode_pdp11_f, + decode_pdp11_f, + 2, + 1, + 24, + 24, + -127, + 127, + 15, + false, + false, + false, + false, + false + }; + +const struct real_format pdp11_d_format = + { + encode_pdp11_d, + decode_pdp11_d, + 2, + 1, + 56, + 56, + -127, + 127, + 15, + false, + false, + false, + false, + false + }; + +static void +encode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf, + const REAL_VALUE_TYPE *r) +{ + (*vax_f_format.encode) (fmt, buf, r); + buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16); +} + +static void +decode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED, + REAL_VALUE_TYPE *r, const long *buf) +{ + long tbuf; + tbuf = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16); + (*vax_f_format.decode) (fmt, r, &tbuf); +} + +static void +encode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf, + const REAL_VALUE_TYPE *r) +{ + (*vax_d_format.encode) (fmt, buf, r); + buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16); + buf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16); +} + +static void +decode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED, + REAL_VALUE_TYPE *r, const long *buf) +{ + long tbuf[2]; + tbuf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16); + tbuf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16); + (*vax_d_format.decode) (fmt, r, tbuf); +} + /* This is where the condition code register lives. */ /* rtx cc0_reg_rtx; - no longer needed? */ @@ -683,22 +767,12 @@ output_move_quad (rtx *operands) { if (GET_CODE (operands[1]) == CONST_DOUBLE) { - /* floats only. not yet supported! - - -- compute it into PDP float format, - internally, - just use IEEE and ignore possible problems ;-) - - we might get away with it !!!! */ - - abort(); - -#ifndef HOST_WORDS_BIG_ENDIAN - latehalf[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1])); - operands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1])); -#else /* HOST_WORDS_BIG_ENDIAN */ - latehalf[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1])); - operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1])); -#endif /* HOST_WORDS_BIG_ENDIAN */ + REAL_VALUE_TYPE r; + long dval[2]; + REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]); + REAL_VALUE_TO_TARGET_DOUBLE (r, dval); + latehalf[1] = GEN_INT (dval[1]); + operands[1] = GEN_INT (dval[0]); } else if (GET_CODE(operands[1]) == CONST_INT) { @@ -1591,6 +1665,21 @@ legitimate_address_p (enum machine_mode mode, rtx address) /* #undef REG_OK_STRICT */ } +/* This function checks whether a real value can be encoded as + a literal, i.e., addressing mode 27. In that mode, real values + are one word values, so the remaining 48 bits have to be zero. */ +int +legitimate_const_double_p (rtx address) +{ + REAL_VALUE_TYPE r; + long sval[2]; + REAL_VALUE_FROM_CONST_DOUBLE (r, address); + REAL_VALUE_TO_TARGET_DOUBLE (r, sval); + if ((sval[0] & 0xffff) == 0 && sval[1] == 0) + return 1; + return 0; +} + /* 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 use, and for debugging output, which we don't support with this port either. diff --git a/gcc/config/pdp11/pdp11.h b/gcc/config/pdp11/pdp11.h index f84e99f847e..6bc37685e45 100644 --- a/gcc/config/pdp11/pdp11.h +++ b/gcc/config/pdp11/pdp11.h @@ -167,14 +167,27 @@ extern int target_flags; /* Define this if most significant byte of a word is the lowest numbered. */ #define BYTES_BIG_ENDIAN 0 -/* Define this if most significant word of a multiword number is numbered. */ +/* Define this if most significant word of a multiword number is first. */ #define WORDS_BIG_ENDIAN 1 +/* Define that floats are in VAX order, not high word first as for ints. */ +#define FLOAT_WORDS_BIG_ENDIAN 0 + /* Width of a word, in units (bytes). UNITS OR BYTES - seems like units */ #define UNITS_PER_WORD 2 +/* This machine doesn't use IEEE floats. */ +/* Because the pdp11 (at least Unix) convention for 32 bit ints is + big endian, opposite for what you need for float, the vax float + conversion routines aren't actually used directly. But the underlying + format is indeed the vax/pdp11 float format. */ +#define TARGET_FLOAT_FORMAT VAX_FLOAT_FORMAT + +extern const struct real_format pdp11_f_format; +extern const struct real_format pdp11_d_format; + /* Maximum sized of reasonable data type DImode or Dfmode ...*/ #define MAX_FIXED_MODE_SIZE 64 @@ -446,8 +459,8 @@ enum reg_class { NO_REGS, MUL_REGS, GENERAL_REGS, LOAD_FPU_REGS, NO_LOAD_FPU_REG operand as its first argument and the constraint letter as its second operand. - `Q' is for memory references using take more than 1 instruction. - `R' is for memory references which take 1 word for the instruction. */ + `Q' is for memory references that require an extra word after the opcode. + `R' is for memory references which are encoded within the opcode. */ #define EXTRA_CONSTRAINT(OP,CODE) \ ((GET_CODE (OP) != MEM) ? 0 \ @@ -678,7 +691,7 @@ extern int may_call_alloca; /* Maximum number of registers that can appear in a valid memory address. */ -#define MAX_REGS_PER_ADDRESS 2 +#define MAX_REGS_PER_ADDRESS 1 /* Recognize any constant value that is a valid address. */ @@ -687,7 +700,8 @@ extern int may_call_alloca; /* Nonzero if the constant value X is a legitimate general operand. It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ -#define LEGITIMATE_CONSTANT_P(X) (TARGET_FPU? 1: !(GET_CODE(X) == CONST_DOUBLE)) +#define LEGITIMATE_CONSTANT_P(X) \ + (GET_CODE (X) != CONST_DOUBLE || legitimate_const_double_p (X)) /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx and check its validity for a certain class. @@ -1078,9 +1092,11 @@ extern struct rtx_def *cc0_reg_rtx; else if (GET_CODE (X) == MEM) \ output_address (XEXP (X, 0)); \ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != SImode) \ - { char buf[30]; \ - real_to_decimal (buf, CONST_DOUBLE_REAL_VALUE (X), sizeof (buf), 0, 1); \ - fprintf (FILE, "$0F%s", buf); } \ + { REAL_VALUE_TYPE r; \ + long sval[2]; \ + REAL_VALUE_FROM_CONST_DOUBLE (r, X); \ + REAL_VALUE_TO_TARGET_DOUBLE (r, sval); \ + fprintf (FILE, "$%#o", sval[0] >> 16); } \ else { putc ('$', FILE); output_addr_const_pdp11 (FILE, X); }} /* Print a memory address as an operand to reference that memory location. */ -- 2.30.2