diff options
Diffstat (limited to 'gcc/config/v850/v850.md')
-rw-r--r-- | gcc/config/v850/v850.md | 168 |
1 files changed, 113 insertions, 55 deletions
diff --git a/gcc/config/v850/v850.md b/gcc/config/v850/v850.md index 0ba10ca0cc0..7eef0c639ae 100644 --- a/gcc/config/v850/v850.md +++ b/gcc/config/v850/v850.md @@ -1,5 +1,5 @@ ;; GCC machine description for NEC V850 -;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. +;; Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. ;; Contributed by Jeff Law (law@cygnus.com). @@ -36,6 +36,11 @@ (define_attr "length" "" (const_int 200)) +(define_attr "long_calls" "yes,no" + (const (if_then_else (symbol_ref "TARGET_LONG_CALLS") + (const_string "yes") + (const_string "no")))) + ;; Types of instructions (for scheduling purposes). (define_attr "type" "load,mult,other" @@ -397,7 +402,7 @@ (set_attr "cc" "clobber")]) (define_insn "*v850_clr1_2" - [(set (match_operand:HI 0 "memory_operand" "=m") + [(set (match_operand:HI 0 "indirect_operand" "=m") (subreg:HI (and:SI (subreg:SI (match_dup 0) 0) (match_operand:HI 1 "not_power_of_two_operand" "")) 0))] @@ -417,7 +422,7 @@ (set_attr "cc" "clobber")]) (define_insn "*v850_clr1_3" - [(set (match_operand:SI 0 "memory_operand" "=m") + [(set (match_operand:SI 0 "indirect_operand" "=m") (and:SI (match_dup 0) (match_operand:SI 1 "not_power_of_two_operand" "")))] "" @@ -461,7 +466,7 @@ (set_attr "cc" "clobber")]) (define_insn "*v850_set1_2" - [(set (match_operand:HI 0 "memory_operand" "=m") + [(set (match_operand:HI 0 "indirect_operand" "=m") (subreg:HI (ior:SI (subreg:SI (match_dup 0) 0) (match_operand 1 "power_of_two_operand" "")) 0))] "" @@ -485,7 +490,7 @@ (set_attr "cc" "clobber")]) (define_insn "*v850_set1_3" - [(set (match_operand:SI 0 "memory_operand" "=m") + [(set (match_operand:SI 0 "indirect_operand" "=m") (ior:SI (match_dup 0) (match_operand 1 "power_of_two_operand" "")))] "" @@ -534,7 +539,7 @@ (set_attr "cc" "clobber")]) (define_insn "*v850_not1_2" - [(set (match_operand:HI 0 "memory_operand" "=m") + [(set (match_operand:HI 0 "indirect_operand" "=m") (subreg:HI (xor:SI (subreg:SI (match_dup 0) 0) (match_operand 1 "power_of_two_operand" "")) 0))] "" @@ -558,7 +563,7 @@ (set_attr "cc" "clobber")]) (define_insn "*v850_not1_3" - [(set (match_operand:SI 0 "memory_operand" "=m") + [(set (match_operand:SI 0 "indirect_operand" "=m") (xor:SI (match_dup 0) (match_operand 1 "power_of_two_operand" "")))] "" @@ -969,19 +974,44 @@ if (! call_address_operand (XEXP (operands[0], 0)) || TARGET_LONG_CALLS) XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0)); - emit_call_insn (gen_call_internal (XEXP (operands[0], 0), operands[1])); + if (TARGET_LONG_CALLS) + emit_call_insn (gen_call_internal_long (XEXP (operands[0], 0), operands[1])); + else + emit_call_insn (gen_call_internal_short (XEXP (operands[0], 0), operands[1])); + DONE; }") -(define_insn "call_internal" +(define_insn "call_internal_short" [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r")) (match_operand:SI 1 "general_operand" "g,g")) (clobber (reg:SI 31))] - "" + "! TARGET_LONG_CALLS" "@ jarl %0,r31 - jarl .+4,r31\\n\\tadd 4,r31\\n\\tjmp %0" - [(set_attr "length" "4,8")]) + jarl .+4,r31\\;add 4,r31\\;jmp %0" + [(set_attr "length" "4,8")] +) + +(define_insn "call_internal_long" + [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r")) + (match_operand:SI 1 "general_operand" "g,g")) + (clobber (reg:SI 31))] + "TARGET_LONG_CALLS" + "* + { + if (which_alternative == 0) + { + if (GET_CODE (operands[0]) == REG) + return \"jarl %0,r31\"; + else + return \"movhi hi(%0), r0, r11\\;movea lo(%0), r11, r11\\;jarl .+4,r31\\;add 4, r31\\;jmp r11\"; + } + else + return \"jarl .+4,r31\\;add 4,r31\\;jmp %0\"; + }" + [(set_attr "length" "16,8")] +) ;; Call subroutine, returning value in operand 0 ;; (which must be a hard register). @@ -996,22 +1026,50 @@ if (! call_address_operand (XEXP (operands[1], 0)) || TARGET_LONG_CALLS) XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0)); - emit_call_insn (gen_call_value_internal (operands[0], - XEXP (operands[1], 0), - operands[2])); + if (TARGET_LONG_CALLS) + emit_call_insn (gen_call_value_internal_long (operands[0], + XEXP (operands[1], 0), + operands[2])); + else + emit_call_insn (gen_call_value_internal_short (operands[0], + XEXP (operands[1], 0), + operands[2])); DONE; }") -(define_insn "call_value_internal" +(define_insn "call_value_internal_short" [(set (match_operand 0 "" "=r,r") (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r")) (match_operand:SI 2 "general_operand" "g,g"))) (clobber (reg:SI 31))] - "" + "! TARGET_LONG_CALLS" "@ jarl %1,r31 - jarl .+4,r31\\n\\tadd 4,r31\\n\\tjmp %1" - [(set_attr "length" "4,8")]) + jarl .+4,r31\\;add 4,r31\\;jmp %1" + [(set_attr "length" "4,8")] +) + +(define_insn "call_value_internal_long" + [(set (match_operand 0 "" "=r,r") + (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r")) + (match_operand:SI 2 "general_operand" "g,g"))) + (clobber (reg:SI 31))] + "TARGET_LONG_CALLS" + "* + { + if (which_alternative == 0) + { + if (GET_CODE (operands[1]) == REG) + return \"jarl %1, r31\"; + else + /* Reload can generate this pattern... */ + return \"movhi hi(%1), r0, r11\\;movea lo(%1), r11, r11\\;jarl .+4, r31\\;add 4, r31\\;jmp r11\"; + } + else + return \"jarl .+4, r31\\;add 4, r31\\;jmp %1\"; + }" + [(set_attr "length" "16,8")] +) (define_insn "nop" [(const_int 0)] @@ -1180,45 +1238,15 @@ "TARGET_PROLOG_FUNCTION" "* return construct_save_jarl (operands[0]); " - [(set_attr "length" "4") + [(set (attr "length") (if_then_else (eq_attr "long_calls" "yes") + (const_string "16") + (const_string "4"))) (set_attr "cc" "clobber")]) - -;; Initialize an interrupt function. Do not depend on TARGET_PROLOG_FUNCTION. -(define_insn "save_interrupt" - [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -16))) - (set (mem:SI (reg:SI 3)) (reg:SI 30)) - (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 10)) - (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 4)) - (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 1))] - "" - "add -16,sp\;st.w r10,12[sp]\;jarl __save_interrupt,r10" - [(set_attr "length" "12") - (set_attr "cc" "clobber")]) - - -;; Save all registers except for the registers saved in save_interrupt when -;; an interrupt function makes a call. -;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and -;; all of memory. This blocks insns from being moved across this point. -;; This is needed because the rest of the compiler is not ready to handle -;; insns this complicated. - -(define_insn "save_all_interrupt" - [(unspec_volatile [(const_int 0)] 0)] - "" - "jarl __save_all_interrupt,r10" - [(set_attr "length" "4") - (set_attr "cc" "clobber")]) - - - - ;; This pattern will match a return RTX followed by any number of pop RTXs ;; and possible a stack adjustment as well. These RTXs will be turned into ;; a suitable call to a worker function. - (define_insn "" [(match_parallel 0 "pattern_is_ok_for_epilogue" [(return) @@ -1230,9 +1258,23 @@ "TARGET_PROLOG_FUNCTION && TARGET_V850" "* return construct_restore_jr (operands[0]); " - [(set_attr "length" "4") + [(set (attr "length") (if_then_else (eq_attr "long_calls" "yes") + (const_string "12") + (const_string "4"))) (set_attr "cc" "clobber")]) +;; Initialize an interrupt function. Do not depend on TARGET_PROLOG_FUNCTION. +(define_insn "save_interrupt" + [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -16))) + (set (mem:SI (reg:SI 3)) (reg:SI 30)) + (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 10)) + (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 4)) + (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 1))] + "TARGET_V850 && ! TARGET_LONG_CALLS" + "add -16,sp\;st.w r10,12[sp]\;jarl __save_interrupt,r10" + [(set_attr "length" "12") + (set_attr "cc" "clobber")]) + ;; Restore r1, r4, r10, and return from the interrupt (define_insn "restore_interrupt" [(return) @@ -1246,6 +1288,22 @@ [(set_attr "length" "4") (set_attr "cc" "clobber")]) + +;; Save all registers except for the registers saved in save_interrupt when +;; an interrupt function makes a call. +;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and +;; all of memory. This blocks insns from being moved across this point. +;; This is needed because the rest of the compiler is not ready to handle +;; insns this complicated. + +(define_insn "save_all_interrupt" + [(unspec_volatile [(const_int 0)] 0)] + "TARGET_V850 && ! TARGET_LONG_CALLS" + "jarl __save_all_interrupt,r10" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + + ;; Restore all registers saved when an interrupt function makes a call. ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and ;; all of memory. This blocks insns from being moved across this point. @@ -1254,7 +1312,7 @@ (define_insn "restore_all_interrupt" [(unspec_volatile [(const_int 0)] 1)] - "" + "TARGET_V850 && ! TARGET_LONG_CALLS" "jarl __restore_all_interrupt,r10" [(set_attr "length" "4") (set_attr "cc" "clobber")]) @@ -1266,7 +1324,7 @@ (set (mem:SI (plus:SI (reg:SI 3) (const_int 8))) (reg:SI 8)) (set (mem:SI (plus:SI (reg:SI 3) (const_int 12))) (reg:SI 9)) (clobber (reg:SI 10))] - "TARGET_PROLOG_FUNCTION" + "TARGET_PROLOG_FUNCTION && ! TARGET_LONG_CALLS" "jarl __save_r6_r9,r10" [(set_attr "length" "4") (set_attr "cc" "clobber")]) |