+2002-12-20 Ian Dall <ian@sibyl.beware.dropbear.id.au>
+
+ * config/ns32k/ns32k.md (movdi): Use "l" instead of "f" to match
+ all registers capable of holding a double float.
+ (*rcond): change name of "reverse branch" insns to
+ something more meaningful.
+ (*rbgt, *rblt, *rbge, *rble): Reverse branches to handle IEEE
+ comparisons properly.
+ (*ffs): Change operand 0 from write to read-modify-write.
+ (*ffsssi2): Drop constraints from define_expand.
+
+ * config/ns32k/ns32k.h (STORE_RATIO, STORE_BY_PIECES): Avoid using
+ MOVE_RATIO as default for store operations.
+
+ * config/ns32k/ns32k.h (enum reg_class, REG_CLASS_NAMES): Add
+ LONG_REGS class.
+ (CANNOT_CHANGE_MODE_CLASS): Can't subreg LONG_REGS.
+ (GO_IF_LEGITIMATE_ADDRESS): Remove spurious abort().
+ * config/ns32k/ns32k.c (regclass_map): Add LONG_REGS class.
+
+ * config/ns32k/STATUS: New File
+ * config/ns32k/NOTES: New file.
+
2002-12-20 Hartmut Penner <hpenner@de.ibm.com>
* doc/invoke.texi: Document -mzarch, -mesa, -mcpu= and -march=
--- /dev/null
+Copyright (C) 2002
+Free Software Foundation, Inc.
+
+ Implementation Notes
+ ====================
+
+IEEE floating point comparisons
+
+Ian Dall <ian@beware.dropbear.id.au>
+------------------------------------
+
+The ns32x81 fpu handles most operands in hardware, but traps on NaN,
+Inf and Denormalized numbers. The correct behaviour can be handled by
+the trap handler. This is mostly transparent to the compiler, but in
+the case of floating point comparisions, the trap handler and the
+compiler must co-operate.
+
+Comparing a Nan with anything (including another Nan) is an unordered
+comparison and a NE test should be true and any other test should be
+false. There is nothing the trap handler can do to the condition codes
+to make, for example ble and bgt (the machine instructions, not the
+gcc insn's) both fail.
+
+The L flag (normally used for unsigned comparisons) is cleared by a floating
+point compare. So, it is possible for the trap handler to communicate that
+it has seen a NaN by setting this flag.
+
+This can get confusing so the following documents the reasoning. There
+are only 3 flags of significance, N, Z and L. In what follows AB is
+the conjunction of A and B ("and") A+B is the disjunction of A and B
+("or"), upper case represents true and lower case represents false. So
+"Zl" is "Z AND (NOT L)".
+
+Also, we can require that the trap handler clears N and Z, whenever it
+sets L. This means that in many cases, we do not need to test if L is
+set or clear. The operations we require are:
+
+ Operator Expression Check L
+ GT Nl No
+ LT znl Yes
+ GE (Z+N)l No
+ LE nl Yes
+ EQ Zl No
+ NE z+L No
+
+
+For example, the emitted code for the case of LT is
+
+ bhi 0f
+ blt %0
+ 0:
+
+which is, in effect, "branch if ordered and less than."
+
+We also need insns for the reverse branches. These have the PC and
+the label ref opereands reversed. Thus the reverse bgt has a pattern:
+
+ (set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))
+
+This is identical to a normal branch with the test complimented:
+
+ (set (pc)
+ (if_then_else (not (gt (cc0)
+ (const_int 0)))
+ (label_ref (match_operand 0 "" "")
+ (pc))))
+
+Thus we need a family of (NOT cond) tests. For integers this is easy,
+a reverse blt becomes bge. However, the possibility of unordered
+comparison complicates the floating point case. So, we need to
+compliment the above expressions, using deMorgan's theorem, for the reverse
+branch:
+
+ Operator Expression Check L
+ RGT n+L Yes
+ RLT Z+N+L Yes
+ RGE zn+L Yes
+ RLE N+L Yes
+ REQ z+L No
+ RNE Zl No
+
+For example the emitted code for the case of RLT is
+
+ bge %0
+ bhi %0
+
+which is, in effect "branch if not less than and not unordered."
+
+These extra comparisions are safe if the trap handler doesn't set the
+L flag, since in that case the additional "bhi" instructions are never
+taken. Also, these extra branch instructions are controlled by the
+"-mieee-compare" option.
+
--- /dev/null
+NS32K Port Status Last updated 19 Dec 2002
+
+Recent development of the ns32k port has been as a cross compiler. As
+such a native bootstrap has not been performed. Currently the
+compiler successfully builds a NetBSD kernel and has been tested on
+the testsuite with "make check" configured to remotely execute
+tests on a pc532-netbsd.
+
+There are a few remaining failures in the testsuite, none of which
+result in incorrect code generation or unexpected ICEs.
+
+Here follows comments on the outstanding testsuite failures:
+
+gcc.c-torture/compile/20001226-1.c, -Os
+This typically fails due to a time out or exhausting available memory.
+In the past it has been found to eventually compile in under 6
+minutes, with consuming up to 90MB. The timeout in dejagnu is 5
+minutes.
+
+gcc.c-torture/execute/builtin-constant.c
+I don't understand why this fails. Looking at the generated assembler,
+the first invocation of btest returns "1" and the second "0". Presumably
+the flow analysis is meant to indicate this is a "builtin constant".
+The documentation for __builtin_constant says it is allowed to fail if the
+compiler can't deduce that something is a constant, so the compiler is
+correct if not ideal.
+
+gcc.dg/debug/debug-1.c scan-assembler xyzzy:
+At -O3 level of optimization, variable xyzzy gets eliminated. Isn't it
+reasonable that the debugging info is gone too? Indeed, the
+documentation says this is expected behaviour.
+
+gcc.dg/debug/debug-2.c scan-assembler xyzzy:
+As for the above.
+
+gcc.dg/20010912-1.c
+PIC is supported for the compiler, but we get a link error until we get a
+cross linker which can handle dynamic linking.
+
+gcc.dg/20020304-1.c -O -fssa -fssa-ccp
+ICE -fssa and -fssa-ccp are "experimental" options. Assume not a
+backend problem.
+
+gcc.dg/20021014-1.c (test for excess errors)
+This is a test of the "-p" option. Fails due to lack of mcrt0.o. This
+platform support "-pg" but not "-p"
+
+gcc.dg/20021018-1.c (test for excess errors)
+Fail due to lack of dynamic link support at link time.
+
+gcc.dg/bitfld-3.c (test for excess errors)
+Execution passes, but compilation produces excessive warnings. These warnings
+actually seem reasonable. The code uses __attribute__((aligned (8)), and
+the maximum alignment which makes any sense for this architecture is 4.
+
+gcc.dg/duff-2.c (test for excess errors)
+Execution passes, but compilation produces excessive warnings. Doesn't look
+like a backend problem.
+
+gcc.dg/uninit-A.c -O2 -Wall -S
+Bogus warnings, almost certainly not backend.
+
+gcc.dg/special/weak-1.c execution test
+X This fails for i386 too. I don't understand what the correct behaviour
+for this test is.
+
+gcc.dg/special/gcsec-1.c (test for excess errors)
+a.out deficiency. -ffunction-sections and -fdata-sections not supported.
GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
FLOAT_REG0, LONG_FLOAT_REG0, FLOAT_REGS, FLOAT_REGS,
FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS,
- FP_REGS, FP_REGS, FP_REGS, FP_REGS,
- FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+ LONG_REGS, LONG_REGS, LONG_REGS, LONG_REGS,
+ LONG_REGS, LONG_REGS, LONG_REGS, LONG_REGS,
FRAME_POINTER_REG, STACK_POINTER_REG
};
enum reg_class
{ NO_REGS, GENERAL_REGS, FLOAT_REG0, LONG_FLOAT_REG0, FLOAT_REGS,
- FP_REGS, GEN_AND_FP_REGS, FRAME_POINTER_REG, STACK_POINTER_REG,
- GEN_AND_MEM_REGS, ALL_REGS, LIM_REG_CLASSES };
+ LONG_REGS, FP_REGS, GEN_AND_FP_REGS, FRAME_POINTER_REG,
+ STACK_POINTER_REG, GEN_AND_MEM_REGS, ALL_REGS, LIM_REG_CLASSES };
#define N_REG_CLASSES (int) LIM_REG_CLASSES
/* Give names of register classes as strings for dump file. */
-#define REG_CLASS_NAMES \
+#define REG_CLASS_NAMES \
{"NO_REGS", "GENERAL_REGS", "FLOAT_REG0", "LONG_FLOAT_REG0", "FLOAT_REGS", \
- "FP_REGS", "GEN_AND_FP_REGS", "FRAME_POINTER_REG", "STACK_POINTER_REG", \
- "GEN_AND_MEM_REGS", "ALL_REGS" }
+ "LONG_REGS", "FP_REGS", "GEN_AND_FP_REGS", "FRAME_POINTER_REG", \
+ "STACK_POINTER_REG", "GEN_AND_MEM_REGS", "ALL_REGS" }
/* Define which registers fit in which classes.
This is an initializer for a vector of HARD_REG_SET
{0x100}, /* FLOAT_REG0 */ \
{0x300}, /* LONG_FLOAT_REG0 */ \
{0xff00}, /* FLOAT_REGS */ \
+ {0xff0000}, /* LONG_REGS */ \
{0xffff00}, /* FP_REGS */ \
{0xffffff}, /* GEN_AND_FP_REGS */ \
{0x1000000}, /* FRAME_POINTER_REG */ \
((ns32k_reg_class_contents[CLASS1][0] \
& ~ns32k_reg_class_contents[CLASS2][0]) == 0)
+
+/* LONG_REGS are registers which can only hold double precision floats
+ * and can only be accessable by long float instructions.
+ */
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
+ (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? LONG_REGS : NO_REGS)
+
/* The same information, inverted:
Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression
else if (GET_CODE (xfooy) == PRE_DEC) \
{ \
if (REGNO (XEXP (xfooy, 0)) == STACK_POINTER_REGNUM) goto ADDR; \
- else abort (); \
} \
}
We have a smart movstrsi insn */
#define MOVE_RATIO 0
+#define STORE_RATIO (optimize_size ? 3 : 15)
+#define STORE_BY_PIECES_P(SIZE, ALIGN) \
+ (move_by_pieces_ninsns (SIZE, ALIGN) < (unsigned int) STORE_RATIO)
+
+
/* Nonzero if access to memory by bytes is slow and undesirable. */
#define SLOW_BYTE_ACCESS 0
;;- Machine description for GNU compiler, ns32000 Version
-;; Copyright (C) 1988, 1994, 1996, 1998, 1999, 2000, 2001
+;; Copyright (C) 1988, 1994, 1996, 1998, 1999, 2000, 2001, 2002
;; Free Software Foundation, Inc.
;; Contributed by Michael Tiemann (tiemann@cygnus.com)
"movmd %1,%0,4")
(define_insn "movdi"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=rm<,*f,rm")
- (match_operand:DI 1 "general_operand" "gF,g,*f"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm<,*l,rm")
+ (match_operand:DI 1 "general_operand" "gF,g,*l"))]
""
"*
{
""
"bls %l0")
\f
-;; "Reversed" jump instructions. Are these ever generated?
+;; "Reversed" jump instructions.
-(define_insn "*bne"
+(define_insn "*rbeq"
[(set (pc)
(if_then_else (eq (cc0)
(const_int 0))
return \"bfs %l0\";
else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
return \"bfc %l0\";
- else return \"bne %l0\";
+ else
+ return \"bne %l0\";
}")
-(define_insn "*beq"
+(define_insn "*rbne"
[(set (pc)
(if_then_else (ne (cc0)
(const_int 0))
else return \"beq %l0\";
}")
-(define_insn "*ble"
+(define_insn "*rbgt"
[(set (pc)
(if_then_else (gt (cc0)
(const_int 0))
"*
{
if (cc_prev_status.flags & CC_UNORD)
- return \"bhi 0f\;ble %l0\;0:\";
+ return \"ble %l0\;bhi %l0\";
else
return \"ble %l0\";
}")
-(define_insn "*bleu"
+(define_insn "*rbgtu"
[(set (pc)
(if_then_else (gtu (cc0)
(const_int 0))
""
"bls %l0")
-(define_insn "*bge"
+(define_insn "*rblt"
[(set (pc)
(if_then_else (lt (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
- "bge %l0")
+ "*
+{
+ if (cc_prev_status.flags & CC_UNORD)
+ return \"bge %l0\;bhi %l0\";
+ else
+ return \"bge %l0\";
+}")
-(define_insn "*bgeu"
+(define_insn "*rbltu"
[(set (pc)
(if_then_else (ltu (cc0)
(const_int 0))
""
"bhs %l0")
-(define_insn "*blt"
+(define_insn "*rbge"
[(set (pc)
(if_then_else (ge (cc0)
(const_int 0))
"*
{
if (cc_prev_status.flags & CC_UNORD)
- return \"bhi 0f\;blt %l0\;0:\";
+ return \"blt %l0\;bhi %l0\";
else
return \"blt %l0\";
}")
-(define_insn "*bltu"
+(define_insn "*rbgeu"
[(set (pc)
(if_then_else (geu (cc0)
(const_int 0))
""
"blo %l0")
-(define_insn "*bgt"
+(define_insn "*rble"
[(set (pc)
(if_then_else (le (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
- "bgt %l0")
+ "*
+{
+ if (cc_prev_status.flags & CC_UNORD)
+ return \"bgt %l0\;bhi %l0\";
+ else
+ return \"bgt %l0\";
+}")
-(define_insn "*bgtu"
+(define_insn "*rbleu"
[(set (pc)
(if_then_else (leu (cc0)
(const_int 0))
;; ffs instructions
(define_insn "*ffs"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=ro")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "+ro")
(minus:SI
(plus:SI (ffs:SI (zero_extract:SI
(match_operand:SI 1 "general_operand" "g")
(match_dup 0))
(const_int 1)))]
""
- "ffsd %1,%0; bfc 1f; addqd %$-1,%0; 1:")
+ "ffsd %1,%0\;bfc 1f\;addqd %$-1,%0\;1:")
(define_expand "ffssi2"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (const_int 0))
+ [(set (match_operand:SI 0 "nonimmediate_operand" "") (const_int 0))
(set (match_dup 0)
(minus:SI
(plus:SI (ffs:SI (zero_extract:SI