| /* Definitions of target machine for GNU compiler. TMS320C[34]x |
| Copyright (C) 2002 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 2, 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 COPYING. If not, write to |
| the Free Software Foundation, 59 Temple Place - Suite 330, |
| Boston, MA 02111-1307, USA. */ |
| |
| /* 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 can not 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); |