109 lines
5.0 KiB
Modula-2
109 lines
5.0 KiB
Modula-2
/* Definitions of target machine for GNU compiler. TMS320C[34]x
|
|
Copyright (C) 2002, 2004, 2007 Free Software Foundation, Inc.
|
|
|
|
Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
|
|
and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl).
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3, or (at your option)
|
|
any later version.
|
|
|
|
GCC is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GCC; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
/* C4x wants 1- and 2-word float modes, in its own peculiar format.
|
|
FIXME: Give this port a way to get rid of SFmode, DFmode, and all
|
|
the other modes it doesn't use. */
|
|
FLOAT_MODE (QF, 1, c4x_single_format);
|
|
FLOAT_MODE (HF, 2, c4x_extended_format);
|
|
RESET_FLOAT_FORMAT (SF, 0); /* not used */
|
|
RESET_FLOAT_FORMAT (DF, 0); /* not used */
|
|
|
|
/* Add any extra modes needed to represent the condition code.
|
|
|
|
On the C4x, we have a "no-overflow" mode which is used when an ADD,
|
|
SUB, NEG, or MPY insn is used to set the condition code. This is
|
|
to prevent the combiner from optimizing away a following CMP of the
|
|
result with zero when a signed conditional branch or load insn
|
|
follows.
|
|
|
|
The problem is a subtle one and deals with the manner in which the
|
|
negative condition (N) flag is used on the C4x. This flag does not
|
|
reflect the status of the actual result but of the ideal result had
|
|
no overflow occurred (when considering signed operands).
|
|
|
|
For example, 0x7fffffff + 1 => 0x80000000 Z=0 V=1 N=0 C=0. Here
|
|
the flags reflect the untruncated result, not the actual result.
|
|
While the actual result is less than zero, the N flag is not set
|
|
since the ideal result of the addition without truncation would
|
|
have been positive.
|
|
|
|
Note that the while the N flag is handled differently to most other
|
|
architectures, the use of it is self consistent and is not the
|
|
cause of the problem.
|
|
|
|
Logical operations set the N flag to the MSB of the result so if
|
|
the result is negative, N is 1. However, integer and floating
|
|
point operations set the N flag to be the MSB of the result
|
|
exclusive ored with the overflow (V) flag. Thus if an overflow
|
|
occurs and the result does not have the MSB set (i.e., the result
|
|
looks like a positive number), the N flag is set. Conversely, if
|
|
an overflow occurs and the MSB of the result is set, N is set to 0.
|
|
Thus the N flag represents the sign of the result if it could have
|
|
been stored without overflow but does not represent the apparent
|
|
sign of the result. Note that most architectures set the N flag to
|
|
be the MSB of the result.
|
|
|
|
The C4x approach to setting the N flag simplifies signed
|
|
conditional branches and loads which only have to test the state of
|
|
the N flag, whereas most architectures have to look at both the N
|
|
and V flags. The disadvantage is that there is no flag giving the
|
|
status of the sign bit of the operation. However, there are no
|
|
conditional load or branch instructions that make use of this
|
|
feature (e.g., BMI---branch minus) instruction. Note that BN and
|
|
BLT are identical in the C4x.
|
|
|
|
To handle the problem where the N flag is set differently whenever
|
|
there is an overflow we use a different CC mode, CC_NOOVmode which
|
|
says that the CC reflects the comparison of the result against zero
|
|
if no overflow occurred.
|
|
|
|
For example,
|
|
|
|
[(set (reg:CC_NOOV 21)
|
|
(compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "")
|
|
(match_operand:QI 2 "src_operand" ""))
|
|
(const_int 0)))
|
|
(set (match_operand:QI 0 "ext_reg_operand" "")
|
|
(minus:QI (match_dup 1)
|
|
(match_dup 2)))]
|
|
|
|
Note that there is no problem for insns that don't return a result
|
|
like CMP, since the CC reflects the effect of operation.
|
|
|
|
An example of a potential problem is when GCC
|
|
converts (LTU (MINUS (0x80000000) (0x7fffffff) (0x80000000)))
|
|
to (LEU (MINUS (0x80000000) (0x7fffffff) (0x7fffffff)))
|
|
to (GE (MINUS (0x80000000) (0x7fffffff) (0x00000000)))
|
|
|
|
Now (MINUS (0x80000000) (0x7fffffff)) returns 0x00000001 but the
|
|
C4x sets the N flag since the result without overflow would have
|
|
been 0xffffffff when treating the operands as signed integers.
|
|
Thus (GE (MINUS (0x80000000) (0x7fffffff) (0x00000000))) sets the N
|
|
flag but (GE (0x00000001)) does not set the N flag.
|
|
|
|
The upshot is that we cannot use signed branch and conditional
|
|
load instructions after an add, subtract, neg, abs or multiply.
|
|
We must emit a compare insn to check the result against 0. */
|
|
|
|
CC_MODE (CC_NOOV);
|