aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/v850/v850.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/v850/v850.md')
-rw-r--r--gcc/config/v850/v850.md168
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")])