diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/vax/vax-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/vax/vax.c | 69 | ||||
-rw-r--r-- | gcc/config/vax/vax.h | 56 |
4 files changed, 79 insertions, 55 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2de8e1d..86dd337 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2004-03-06 Kazu Hirata <kazu@cs.umass.edu> + + * config/vax/vax-protos.h: Add a prototype for + vax_notice_update_cc. + * config/vax/vax.c (vax_notice_update_cc): New. + * config/vax/vax.h (NOTICE_UPDATE_CC): Call + vax_notice_update_cc. + 2004-03-06 David Edelsohn <edelsohn@gnu.org> * collect2.c (main): Only export initfunc and finifunc if diff --git a/gcc/config/vax/vax-protos.h b/gcc/config/vax/vax-protos.h index 978083b..f97d31a 100644 --- a/gcc/config/vax/vax-protos.h +++ b/gcc/config/vax/vax-protos.h @@ -25,6 +25,7 @@ extern const char *rev_cond_name (rtx); extern void split_quadword_operands (rtx *, rtx *, int); extern void print_operand_address (FILE *, rtx); extern int vax_float_literal (rtx); +extern void vax_notice_update_cc (rtx, rtx); #endif /* RTX_CODE */ #ifdef REAL_VALUE_TYPE diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c index 7695d69..da1b481 100644 --- a/gcc/config/vax/vax.c +++ b/gcc/config/vax/vax.c @@ -788,3 +788,72 @@ vax_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, { return gen_rtx_REG (Pmode, VAX_STRUCT_VALUE_REGNUM); } + +/* Worker function for NOTICE_UPDATE_CC. */ + +void +vax_notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED) +{ + if (GET_CODE (exp) == SET) + { + if (GET_CODE (SET_SRC (exp)) == CALL) + CC_STATUS_INIT; + else if (GET_CODE (SET_DEST (exp)) != ZERO_EXTRACT + && GET_CODE (SET_DEST (exp)) != PC) + { + cc_status.flags = 0; + /* The integer operations below don't set carry or + set it in an incompatible way. That's ok though + as the Z bit is all we need when doing unsigned + comparisons on the result of these insns (since + they're always with 0). Set CC_NO_OVERFLOW to + generate the correct unsigned branches. */ + switch (GET_CODE (SET_SRC (exp))) + { + case NEG: + if (GET_MODE_CLASS (GET_MODE (exp)) == MODE_FLOAT) + break; + case AND: + case IOR: + case XOR: + case NOT: + case MEM: + case REG: + cc_status.flags = CC_NO_OVERFLOW; + break; + default: + break; + } + cc_status.value1 = SET_DEST (exp); + cc_status.value2 = SET_SRC (exp); + } + } + else if (GET_CODE (exp) == PARALLEL + && GET_CODE (XVECEXP (exp, 0, 0)) == SET) + { + if (GET_CODE (SET_SRC (XVECEXP (exp, 0, 0))) == CALL) + CC_STATUS_INIT; + else if (GET_CODE (SET_DEST (XVECEXP (exp, 0, 0))) != PC) + { + cc_status.flags = 0; + cc_status.value1 = SET_DEST (XVECEXP (exp, 0, 0)); + cc_status.value2 = SET_SRC (XVECEXP (exp, 0, 0)); + } + else + /* PARALLELs whose first element sets the PC are aob, + sob insns. They do change the cc's. */ + CC_STATUS_INIT; + } + else + CC_STATUS_INIT; + if (cc_status.value1 && GET_CODE (cc_status.value1) == REG + && cc_status.value2 + && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) + cc_status.value2 = 0; + if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM + && cc_status.value2 + && GET_CODE (cc_status.value2) == MEM) + cc_status.value2 = 0; + /* Actual condition, one line up, should be that value2's address + depends on value1, but that is too much of a pain. */ +} diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h index c2de0f6..3bc04b9 100644 --- a/gcc/config/vax/vax.h +++ b/gcc/config/vax/vax.h @@ -866,61 +866,7 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES }; Do not alter them if the instruction would not alter the cc's. */ #define NOTICE_UPDATE_CC(EXP, INSN) \ -{ if (GET_CODE (EXP) == SET) \ - { if (GET_CODE (SET_SRC (EXP)) == CALL) \ - CC_STATUS_INIT; \ - else if (GET_CODE (SET_DEST (EXP)) != ZERO_EXTRACT \ - && GET_CODE (SET_DEST (EXP)) != PC) \ - { \ - cc_status.flags = 0; \ - /* The integer operations below don't set carry or \ - set it in an incompatible way. That's ok though \ - as the Z bit is all we need when doing unsigned \ - comparisons on the result of these insns (since \ - they're always with 0). Set CC_NO_OVERFLOW to \ - generate the correct unsigned branches. */ \ - switch (GET_CODE (SET_SRC (EXP))) \ - { \ - case NEG: \ - if (GET_MODE_CLASS (GET_MODE (EXP)) == MODE_FLOAT)\ - break; \ - case AND: \ - case IOR: \ - case XOR: \ - case NOT: \ - case MEM: \ - case REG: \ - cc_status.flags = CC_NO_OVERFLOW; \ - break; \ - default: \ - break; \ - } \ - cc_status.value1 = SET_DEST (EXP); \ - cc_status.value2 = SET_SRC (EXP); } } \ - else if (GET_CODE (EXP) == PARALLEL \ - && GET_CODE (XVECEXP (EXP, 0, 0)) == SET) \ - { \ - if (GET_CODE (SET_SRC (XVECEXP (EXP, 0, 0))) == CALL) \ - CC_STATUS_INIT; \ - else if (GET_CODE (SET_DEST (XVECEXP (EXP, 0, 0))) != PC) \ - { cc_status.flags = 0; \ - cc_status.value1 = SET_DEST (XVECEXP (EXP, 0, 0)); \ - cc_status.value2 = SET_SRC (XVECEXP (EXP, 0, 0)); } \ - else \ - /* PARALLELs whose first element sets the PC are aob, \ - sob insns. They do change the cc's. */ \ - CC_STATUS_INIT; } \ - else CC_STATUS_INIT; \ - if (cc_status.value1 && GET_CODE (cc_status.value1) == REG \ - && cc_status.value2 \ - && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) \ - cc_status.value2 = 0; \ - if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM \ - && cc_status.value2 \ - && GET_CODE (cc_status.value2) == MEM) \ - cc_status.value2 = 0; } -/* Actual condition, one line up, should be that value2's address - depends on value1, but that is too much of a pain. */ + vax_notice_update_cc ((EXP), (INSN)) #define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \ { if (cc_status.flags & CC_NO_OVERFLOW) \ |