diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f30e83542c9..d4432950078 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2003-06-24 Kazu Hirata + + * config/h8300/h8300-protos.h: Add a prototype for + compute_mov_length. + * config/h8300/h8300.c (compute_mov_length): New. + * config/h8300/h8300.md (*movqi_h8300): Use it. + (*movqi_h8300hs): Likewise. + (movstrictqi): Likewise. + (*movhi_h8300): Likewise. + (*movhi_h8300hs): Likewise. + (movstricthi): Likewise. + (*movsi_h8300): Likewise. + (*movsf_h8300): Likewise. + (*movsi_h8300hs): Likewise. + (*movsf_h8300hs): Likewise. + 2003-06-24 Kazu Hirata * jump.c (next_nondeleted_insn): Remove. diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h index d1708698bb2..e7ddff8f1c3 100644 --- a/gcc/config/h8300/h8300-protos.h +++ b/gcc/config/h8300/h8300-protos.h @@ -26,6 +26,7 @@ Boston, MA 02111-1307, USA. */ /* Declarations for functions used in insn-output.c. */ #ifdef RTX_CODE +extern unsigned int compute_mov_length (rtx *); extern const char *output_plussi (rtx *); extern unsigned int compute_plussi_length (rtx *); extern int compute_plussi_cc (rtx *); diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index e82ee9552b3..3a5334bf42c 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -1806,6 +1806,255 @@ bit_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) || code == IOR); } +/* Return the length of mov instruction. */ + +unsigned int +compute_mov_length (rtx *operands) +{ + /* If the mov instruction involves a memory operand, we compute the + length, assuming the largest addressing mode is used, and then + adjust later in the function. Otherwise, we compute and return + the exact length in one step. */ + enum machine_mode mode = GET_MODE (operands[0]); + rtx dest = operands[0]; + rtx src = operands[1]; + rtx addr; + + if (GET_CODE (src) == MEM) + addr = XEXP (src, 0); + else if (GET_CODE (dest) == MEM) + addr = XEXP (dest, 0); + else + addr = NULL_RTX; + + if (TARGET_H8300) + { + unsigned int base_length; + + switch (mode) + { + case QImode: + if (addr == NULL_RTX) + return 2; + + /* The eightbit addressing is available only in QImode, so + go ahead and take care of it. */ + if (h8300_eightbit_constant_address_p (addr)) + return 2; + + base_length = 4; + break; + + case HImode: + if (addr == NULL_RTX) + { + if (REG_P (src)) + return 2; + + if (src == const0_rtx) + return 2; + + return 4; + } + + base_length = 4; + break; + + case SImode: + if (addr == NULL_RTX) + { + if (REG_P (src)) + return 4; + + if (GET_CODE (src) == CONST_INT) + { + if (src == const0_rtx) + return 4; + + if ((INTVAL (src) & 0xffff) == 0) + return 6; + + if ((INTVAL (src) & 0xffff) == 0) + return 6; + } + return 8; + } + + base_length = 8; + break; + + case SFmode: + if (addr == NULL_RTX) + { + if (REG_P (src)) + return 4; + + if (src == const0_rtx) + return 2; + + return 6; + } + + base_length = 8; + break; + + default: + abort (); + } + + /* Adjust the length based on the addressing mode used. + Specifically, we subtract the difference between the actual + length and the longest one, which is @(d:16,Rs). For SImode + and SFmode, we double the adjustment because two mov.w are + used to do the job. */ + + /* @Rs+ and @-Rd are 2 bytes shorter than the longest. */ + if (GET_CODE (addr) == PRE_DEC + || GET_CODE (addr) == POST_INC) + { + if (mode == QImode || mode == HImode) + return base_length - 2; + else + /* In SImode and SFmode, we use two mov.w instructions, so + double the adustment. */ + return base_length - 4; + } + + /* @Rs and @Rd are 2 bytes shorter than the longest. Note that + in SImode and SFmode, the second mov.w involves an address + with displacement, namely @(2,Rs) or @(2,Rd), so we subtract + only 2 bytes. */ + if (GET_CODE (addr) == REG) + return base_length - 2; + + return base_length; + } + else + { + unsigned int base_length; + + switch (mode) + { + case QImode: + if (addr == NULL_RTX) + return 2; + + /* The eightbit addressing is available only in QImode, so + go ahead and take care of it. */ + if (h8300_eightbit_constant_address_p (addr)) + return 2; + + base_length = 8; + break; + + case HImode: + if (addr == NULL_RTX) + { + if (REG_P (src)) + return 2; + + if (src == const0_rtx) + return 2; + + return 4; + } + + base_length = 8; + break; + + case SImode: + if (addr == NULL_RTX) + { + if (REG_P (src)) + { + if (REGNO (src) == MAC_REG || REGNO (dest) == MAC_REG) + return 4; + else + return 2; + } + + if (GET_CODE (src) == CONST_INT) + { + int val = INTVAL (src); + + if (val == 0) + return 2; + + if (val == (val & 0x00ff) || val == (val & 0xff00)) + return 4; + + switch (val & 0xffffffff) + { + case 0xffffffff: + case 0xfffffffe: + case 0xfffffffc: + case 0x0000ffff: + case 0x0000fffe: + case 0xffff0000: + case 0xfffe0000: + case 0x00010000: + case 0x00020000: + return 4; + } + } + return 6; + } + + base_length = 10; + break; + + case SFmode: + if (addr == NULL_RTX) + { + if (REG_P (src)) + return 2; + + if (src == const0_rtx) + return 2; + return 6; + } + + base_length = 10; + break; + + default: + abort (); + } + + /* Adjust the length based on the addressing mode used. + Specifically, we subtract the difference between the actual + length and the longest one, which is @(d:24,ERs). */ + + /* @ERs+ and @-ERd are 6 bytes shorter than the longest. */ + if (GET_CODE (addr) == PRE_DEC + || GET_CODE (addr) == POST_INC) + return base_length - 6; + + /* @ERs and @ERd are 6 bytes shorter than the longest. */ + if (GET_CODE (addr) == REG) + return base_length - 6; + + /* @(d:16,ERs) and @(d:16,ERd) are 4 bytes shorter than the + longest. */ + if (GET_CODE (addr) == PLUS + && GET_CODE (XEXP (addr, 0)) == REG + && GET_CODE (XEXP (addr, 1)) == CONST_INT + && INTVAL (XEXP (addr, 1)) > -32768 + && INTVAL (XEXP (addr, 1)) < 32767) + return base_length - 4; + + /* @aa:16 is 4 bytes shorter than the longest. */ + if (h8300_tiny_constant_address_p (addr)) + return base_length - 4; + + /* @aa:24 is 2 bytes shorter than the longest. */ + if (CONSTANT_P (addr)) + return base_length - 2; + + return base_length; + } +} + const char * output_plussi (rtx *operands) { @@ -4067,101 +4316,6 @@ h8300_adjust_insn_length (rtx insn, int length ATTRIBUTE_UNUSED) if (get_attr_adjust_length (insn) == ADJUST_LENGTH_NO) return 0; - /* Adjust length for reg->mem and mem->reg copies. */ - if (GET_CODE (pat) == SET - && (GET_CODE (SET_SRC (pat)) == MEM - || GET_CODE (SET_DEST (pat)) == MEM)) - { - /* This insn might need a length adjustment. */ - rtx addr; - - if (GET_CODE (SET_SRC (pat)) == MEM) - addr = XEXP (SET_SRC (pat), 0); - else - addr = XEXP (SET_DEST (pat), 0); - - if (TARGET_H8300) - { - /* On the H8/300, we subtract the difference between the - actual length and the longest one, which is @(d:16,ERs). */ - - /* @Rs is 2 bytes shorter than the longest. */ - if (GET_CODE (addr) == REG) - return -2; - - /* @aa:8 is 2 bytes shorter than the longest. */ - if (GET_MODE (SET_SRC (pat)) == QImode - && h8300_eightbit_constant_address_p (addr)) - return -2; - } - else - { - /* On the H8/300H and H8S, we subtract the difference - between the actual length and the longest one, which is - @(d:24,ERs). */ - - /* @ERs is 6 bytes shorter than the longest. */ - if (GET_CODE (addr) == REG) - return -6; - - /* @(d:16,ERs) is 6 bytes shorter than the longest. */ - if (GET_CODE (addr) == PLUS - && GET_CODE (XEXP (addr, 0)) == REG - && GET_CODE (XEXP (addr, 1)) == CONST_INT - && INTVAL (XEXP (addr, 1)) > -32768 - && INTVAL (XEXP (addr, 1)) < 32767) - return -4; - - /* @aa:8 is 6 bytes shorter than the longest. */ - if (GET_MODE (SET_SRC (pat)) == QImode - && h8300_eightbit_constant_address_p (addr)) - return -6; - - /* @aa:16 is 4 bytes shorter than the longest. */ - if (h8300_tiny_constant_address_p (addr)) - return -4; - - /* @aa:24 is 2 bytes shorter than the longest. */ - if (GET_CODE (addr) == CONST_INT) - return -2; - } - } - - /* Loading some constants needs adjustment. */ - if (GET_CODE (pat) == SET - && GET_CODE (SET_SRC (pat)) == CONST_INT - && GET_MODE (SET_DEST (pat)) == SImode - && INTVAL (SET_SRC (pat)) != 0) - { - int val = INTVAL (SET_SRC (pat)); - - if (TARGET_H8300 - && ((val & 0xffff) == 0 - || ((val >> 16) & 0xffff) == 0)) - return -2; - - if (TARGET_H8300H || TARGET_H8300S) - { - if (val == (val & 0xff) - || val == (val & 0xff00)) - return 4 - 6; - - switch (val & 0xffffffff) - { - case 0xffffffff: - case 0xfffffffe: - case 0xfffffffc: - case 0x0000ffff: - case 0x0000fffe: - case 0xffff0000: - case 0xfffe0000: - case 0x00010000: - case 0x00020000: - return 4 - 6; - } - } - } - /* Rotations need various adjustments. */ if (GET_CODE (pat) == SET && (GET_CODE (SET_SRC (pat)) == ROTATE diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index 5533cd8ecdb..ec9f1c6876f 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -179,7 +179,8 @@ mov.b %R1,%X0 mov.b %R1,%X0 mov.b %X1,%R0" - [(set_attr "length" "2,2,2,2,8,8") + [(set (attr "length") + (symbol_ref "compute_mov_length (operands)")) (set_attr "cc" "set_zn,set_znv,set_znv,clobber,set_znv,set_znv")]) (define_expand "movqi" @@ -205,9 +206,8 @@ mov.b %X1,%X0 mov.b %R1,%X0 mov.b %R1,%X0" - [(set_attr_alternative "length" - [(const_int 2) (const_int 2) (const_int 2) - (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))]) + [(set (attr "length") + (symbol_ref "compute_mov_length (operands)")) (set_attr "cc" "set_zn,set_znv,set_znv,set_znv")]) ;; movhi @@ -260,7 +260,8 @@ mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0" - [(set_attr "length" "2,2,2,4,4,4") + [(set (attr "length") + (symbol_ref "compute_mov_length (operands)")) (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")]) (define_insn "*movhi_h8300hs" @@ -276,7 +277,8 @@ mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0" - [(set_attr "length" "2,2,2,4,8,8") + [(set (attr "length") + (symbol_ref "compute_mov_length (operands)")) (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")]) (define_expand "movhi" @@ -302,9 +304,8 @@ mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0" - [(set_attr_alternative "length" - [(const_int 2) (const_int 2) (const_int 4) - (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))]) + [(set (attr "length") + (symbol_ref "compute_mov_length (operands)")) (set_attr "cc" "set_zn,set_znv,set_znv,set_znv")]) ;; movsi @@ -416,7 +417,8 @@ abort (); } }" - [(set_attr "length" "4,4,8,8,4,4") + [(set (attr "length") + (symbol_ref "compute_mov_length (operands)")) (set_attr "cc" "clobber")]) (define_insn "*movsf_h8300" @@ -472,7 +474,8 @@ abort (); } }" - [(set_attr "length" "4,4,8,8,4,4") + [(set (attr "length") + (symbol_ref "compute_mov_length (operands)")) (set_attr "cc" "clobber")]) (define_insn "*movsi_h8300hs" @@ -547,7 +550,8 @@ } return \"mov.l %S1,%S0\"; }" - [(set_attr "length" "2,2,6,4,4,10,10,2,6,4") + [(set (attr "length") + (symbol_ref "compute_mov_length (operands)")) (set_attr "cc" "set_zn,set_znv,clobber,set_znv,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv")]) (define_insn "*movsf_h8300h" @@ -563,7 +567,8 @@ mov.l %S1,%S0 mov.l %S1,%S0 mov.l %S1,%S0" - [(set_attr "length" "2,2,10,10,4,4") + [(set (attr "length") + (symbol_ref "compute_mov_length (operands)")) (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")]) ;; ----------------------------------------------------------------------