(UNSPECV_SAVEW 6)
])
-(define_mode_macro P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
-
;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this
;; a second register class, EXTRA_FP_REGS, exists for the v9 chip. The name
;; is a bit of a misnomer as it covers all 64 fp regs. The corresponding
;; constraint letter is 'e'. To avoid any confusion, 'e' is used instead of
;; 'f' for all DF/TFmode values, including those that are specific to the v8.
+
;; Attribute for cpu type.
;; These must match the values for enum processor_type in sparc.h.
(define_attr "cpu"
(define_delay (eq_attr "type" "return")
[(eq_attr "eligible_for_return_delay" "true") (nil) (nil)])
+
;; Include SPARC DFA schedulers
(include "cypress.md")
(include "ultra1_2.md")
(include "ultra3.md")
+
;; Operand and operator predicates.
(include "predicates.md")
;; the patterns. Finally, we have the DEFINE_SPLITs for some of the scc
;; insns that actually require more than one machine instruction.
-;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
-
(define_expand "cmpsi"
[(set (reg:CC 100)
(compare:CC (match_operand:SI 0 "compare_operand" "")
}
[(set_attr "type" "branch")
(set_attr "branch_type" "reg")])
-\f
+
+
+(define_mode_macro P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
+
;; Load in operand 0 the (absolute) address of operand 1, which is a symbolic
;; value subject to a PC-relative relocation. Operand 2 is a helper function
;; that adds the PC value at the call point to operand 0.
(if_then_else (eq_attr "delayed_branch" "true")
(const_int 3)
(const_int 4)))])
-\f
-;; Move instructions
+
+
+;; Integer move instructions
(define_expand "movqi"
[(set (match_operand:QI 0 "general_operand" "")
;; (reg:DI 2 %g2))
;;
-(define_insn "*movdi_insn_sp32_v9"
+(define_insn "*movdi_insn_sp32"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?e,?e,?W")
+ "=o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
(match_operand:DI 1 "input_operand"
- " J,J,U,T,r,o,i,r, f, T, o, f, e, W, e"))]
- "! TARGET_ARCH64
- && TARGET_V9
+ " J,U,T,r,o,i,r, f, T, o, f, f"))]
+ "! TARGET_V9
&& (register_operand (operands[0], DImode)
- || register_or_zero_operand (operands[1], DImode))"
+ || register_operand (operands[1], DImode))"
"@
- stx\t%%g0, %0
#
std\t%1, %0
ldd\t%1, %0
ldd\t%1, %0
#
#
- fmovd\\t%1, %0
- ldd\\t%1, %0
- std\\t%1, %0"
- [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,fpmove,fpload,fpstore")
- (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,*,*,*")
- (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
+ #"
+ [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
+ (set_attr "length" "2,*,*,2,2,2,2,*,*,2,2,2")])
-(define_insn "*movdi_insn_sp32"
+(define_insn "*movdi_insn_sp32_v9"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
+ "=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?e,?e,?W")
(match_operand:DI 1 "input_operand"
- " J,U,T,r,o,i,r, f, T, o, f, f"))]
- "! TARGET_V9
+ " J,J,U,T,r,o,i,r, f, T, o, f, e, W, e"))]
+ "! TARGET_ARCH64
+ && TARGET_V9
&& (register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode))"
+ || register_or_zero_operand (operands[1], DImode))"
"@
+ stx\t%%g0, %0
#
std\t%1, %0
ldd\t%1, %0
ldd\t%1, %0
#
#
- #"
- [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
- (set_attr "length" "2,*,*,2,2,2,2,*,*,2,2,2")])
-
-;; We don't define V1SI because SI should work just fine.
-(define_mode_macro V64 [DF V2SI V4HI V8QI])
-(define_mode_macro V32 [SF V2HI V4QI])
+ fmovd\\t%1, %0
+ ldd\\t%1, %0
+ std\\t%1, %0"
+ [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,fpmove,fpload,fpstore")
+ (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,*,*,*")
+ (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
(define_insn "*movdi_insn_sp64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m,?e,?e,?W,b")
;; Floating point and vector move instructions
+;; We don't define V1SI because SI should work just fine.
+(define_mode_macro V32 [SF V2HI V4QI])
+
+;; Yes, you guessed it right, the former movsf expander.
+(define_expand "mov<V32:mode>"
+ [(set (match_operand:V32 0 "general_operand" "")
+ (match_operand:V32 1 "general_operand" ""))]
+ "<V32:MODE>mode == SFmode || TARGET_VIS"
+{
+ /* Force constants into memory. */
+ if (GET_CODE (operands[0]) == REG && CONSTANT_P (operands[1]))
+ {
+ /* emit_group_store will send such bogosity to us when it is
+ not storing directly into memory. So fix this up to avoid
+ crashes in output_constant_pool. */
+ if (operands [1] == const0_rtx)
+ operands[1] = CONST0_RTX (<V32:MODE>mode);
+
+ if ((TARGET_VIS || REGNO (operands[0]) < 32)
+ && const_zero_operand (operands[1], <V32:MODE>mode))
+ goto movsf_is_ok;
+
+ /* We are able to build any SF constant in integer registers
+ with at most 2 instructions. */
+ if (REGNO (operands[0]) < 32
+ && <V32:MODE>mode == SFmode)
+ goto movsf_is_ok;
+
+ operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
+ operands[1]));
+ }
+
+ /* Handle sets of MEM first. */
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (register_or_zero_operand (operands[1], <V32:MODE>mode))
+ goto movsf_is_ok;
+
+ if (! reload_in_progress)
+ {
+ operands[0] = validize_mem (operands[0]);
+ operands[1] = force_reg (<V32:MODE>mode, operands[1]);
+ }
+ }
+
+ /* Fixup PIC cases. */
+ if (flag_pic)
+ {
+ if (CONSTANT_P (operands[1])
+ && pic_address_needs_scratch (operands[1]))
+ operands[1] = legitimize_pic_address (operands[1], <V32:MODE>mode, 0);
+
+ if (symbolic_operand (operands[1], <V32:MODE>mode))
+ {
+ operands[1] = legitimize_pic_address (operands[1],
+ <V32:MODE>mode,
+ (reload_in_progress ?
+ operands[0] :
+ NULL_RTX));
+ }
+ }
+
+ movsf_is_ok:
+ ;
+})
+
(define_insn "*movsf_insn"
[(set (match_operand:V32 0 "nonimmediate_operand" "=d,f,*r,*r,*r,*r,f,m,m")
(match_operand:V32 1 "input_operand" "GY,f,*rRY,Q,S,m,m,f,*rGY"))]
[(set (match_dup 0) (high:SF (match_dup 1)))
(set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
-;; Yes, you guessed it right, the former movsf expander.
-(define_expand "mov<V32:mode>"
- [(set (match_operand:V32 0 "general_operand" "")
- (match_operand:V32 1 "general_operand" ""))]
- "<V32:MODE>mode == SFmode || TARGET_VIS"
-{
- /* Force constants into memory. */
- if (GET_CODE (operands[0]) == REG && CONSTANT_P (operands[1]))
- {
- /* emit_group_store will send such bogosity to us when it is
- not storing directly into memory. So fix this up to avoid
- crashes in output_constant_pool. */
- if (operands [1] == const0_rtx)
- operands[1] = CONST0_RTX (<V32:MODE>mode);
-
- if ((TARGET_VIS || REGNO (operands[0]) < 32)
- && const_zero_operand (operands[1], <V32:MODE>mode))
- goto movsf_is_ok;
-
- /* We are able to build any SF constant in integer registers
- with at most 2 instructions. */
- if (REGNO (operands[0]) < 32
- && <V32:MODE>mode == SFmode)
- goto movsf_is_ok;
-
- operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
- operands[1]));
- }
-
- /* Handle sets of MEM first. */
- if (GET_CODE (operands[0]) == MEM)
- {
- if (register_or_zero_operand (operands[1], <V32:MODE>mode))
- goto movsf_is_ok;
-
- if (! reload_in_progress)
- {
- operands[0] = validize_mem (operands[0]);
- operands[1] = force_reg (<V32:MODE>mode, operands[1]);
- }
- }
-
- /* Fixup PIC cases. */
- if (flag_pic)
- {
- if (CONSTANT_P (operands[1])
- && pic_address_needs_scratch (operands[1]))
- operands[1] = legitimize_pic_address (operands[1], <V32:MODE>mode, 0);
-
- if (symbolic_operand (operands[1], <V32:MODE>mode))
- {
- operands[1] = legitimize_pic_address (operands[1],
- <V32:MODE>mode,
- (reload_in_progress ?
- operands[0] :
- NULL_RTX));
- }
- }
-
- movsf_is_ok:
- ;
-})
+(define_mode_macro V64 [DF V2SI V4HI V8QI])
;; Yes, you again guessed it right, the former movdf expander.
(define_expand "mov<V64:mode>"
[(set_attr "type" "load,store,*,*,*")
(set_attr "length" "*,*,2,2,2")])
-(define_insn "*movdf_insn_sp32_v9_no_fpu"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,T,r,o")
- (match_operand:DF 1 "input_operand" "T,U,G,ro,rG"))]
- "! TARGET_FPU
- && TARGET_V9
- && ! TARGET_ARCH64
- && (register_operand (operands[0], DFmode)
- || register_or_zero_operand (operands[1], DFmode))"
- "@
- ldd\t%1, %0
- std\t%1, %0
- stx\t%r1, %0
- #
- #"
- [(set_attr "type" "load,store,store,*,*")
- (set_attr "length" "*,*,*,2,2")])
-
;; We have available v9 double floats but not 64-bit integer registers.
(define_insn "*movdf_insn_sp32_v9"
[(set (match_operand:V64 0 "nonimmediate_operand" "=b,e,e,T,W,U,T,f,*r,o")
(set_attr "length" "*,*,*,*,*,*,*,2,2,2")
(set_attr "fptype" "double,double,*,*,*,*,*,*,*,*")])
+(define_insn "*movdf_insn_sp32_v9_no_fpu"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,T,r,o")
+ (match_operand:DF 1 "input_operand" "T,U,G,ro,rG"))]
+ "! TARGET_FPU
+ && TARGET_V9
+ && ! TARGET_ARCH64
+ && (register_operand (operands[0], DFmode)
+ || register_or_zero_operand (operands[1], DFmode))"
+ "@
+ ldd\t%1, %0
+ std\t%1, %0
+ stx\t%r1, %0
+ #
+ #"
+ [(set_attr "type" "load,store,store,*,*")
+ (set_attr "length" "*,*,*,2,2")])
+
;; We have available both v9 double floats and 64-bit integer registers.
(define_insn "*movdf_insn_sp64"
[(set (match_operand:V64 0 "nonimmediate_operand" "=b,e,e,W,*r,*r,m,*r")
"#"
[(set_attr "length" "4")])
+(define_insn "*movtf_insn_sp64"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,o,r")
+ (match_operand:TF 1 "input_operand" "G,oe,Ger,roG"))]
+ "TARGET_FPU
+ && TARGET_ARCH64
+ && ! TARGET_HARD_QUAD
+ && (register_operand (operands[0], TFmode)
+ || register_or_zero_operand (operands[1], TFmode))"
+ "#"
+ [(set_attr "length" "2")])
+
(define_insn "*movtf_insn_sp64_hq"
[(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,e,m,o,r")
(match_operand:TF 1 "input_operand" "G,e,m,e,rG,roG"))]
[(set_attr "type" "*,fpmove,fpload,fpstore,*,*")
(set_attr "length" "2,*,*,*,2,2")])
-(define_insn "*movtf_insn_sp64"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,o,r")
- (match_operand:TF 1 "input_operand" "G,oe,Ger,roG"))]
- "TARGET_FPU
- && TARGET_ARCH64
- && ! TARGET_HARD_QUAD
- && (register_operand (operands[0], TFmode)
- || register_or_zero_operand (operands[1], TFmode))"
- "#"
- [(set_attr "length" "2")])
-
(define_insn "*movtf_insn_sp64_no_fpu"
[(set (match_operand:TF 0 "nonimmediate_operand" "=r,o")
(match_operand:TF 1 "input_operand" "orG,rG"))]
gen_df_reg (set_src, 1)));
DONE;
})
-\f
-;; SPARC V9 conditional move instructions.
+
+
+;; SPARC-V9 conditional move instructions.
;; We can handle larger constants here for some flavors, but for now we keep
;; it simple and only allow those constants supported by all flavors.
[(set_attr "length" "2")])
\f
-;;- zero extension instructions
+;; Zero-extension instructions
;; These patterns originally accepted general_operands, however, slightly
;; better code is generated by only accepting register_operands, and then
[(set_attr "type" "load")
(set_attr "us3load_type" "3cycle")])
-
;; ??? Write truncdisi pattern using sra?
(define_expand "zero_extendsidi2"
"andcc\t%1, 0xff, %0"
[(set_attr "type" "compare")])
\f
-;;- sign extension instructions
+
+;; Sign-extension instructions
;; These patterns originally accepted general_operands, however, slightly
;; better code is generated by only accepting register_operands, and then
ldsw\t%1, %0"
[(set_attr "type" "shift,sload")
(set_attr "us3load_type" "*,3cycle")])
-\f
+
+
;; Special pattern for optimizing bit-field compares. This is needed
;; because combine uses this as a canonical form.
return "andcc\t%0, %1, %%g0";
}
[(set_attr "type" "compare")])
-\f
+
+
;; Conversions between float, double and long double.
(define_insn "extendsfdf2"
"TARGET_FPU && TARGET_HARD_QUAD"
"fqtod\t%1, %0"
[(set_attr "type" "fp")])
-\f
+
+
;; Conversion between fixed point and floating point.
(define_insn "floatsisf2"
"TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
"emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
-;; Integer Addition/Subtraction.
+
+;; Integer addition/subtraction instructions.
(define_expand "adddi3"
[(set (match_operand:DI 0 "register_operand" "")
"TARGET_ARCH64"
"subcc\t%1, %2, %0"
[(set_attr "type" "compare")])
-\f
-;; Integer Multiply/Divide.
+
+
+;; Integer multiply/divide instructions.
;; The 32 bit multiply/divide instructions are deprecated on v9, but at
;; least in UltraSPARC I, II and IIi it is a win tick-wise.
"TARGET_SPARCLET"
"umacd\t%1, %2, %L0"
[(set_attr "type" "imul")])
-\f
-;; Boolean instructions
+
+
+;; Boolean instructions.
+
;; We define DImode `and' so with DImode `not' we can get
;; DImode `andn'. Other combinations are possible.
"TARGET_ARCH64"
"orcc\t%1, 0, %0"
[(set_attr "type" "compare")])
-\f
+
+
;; Floating point arithmetic instructions.
(define_expand "addtf3"
"TARGET_FPU"
"fsqrts\t%1, %0"
[(set_attr "type" "fpsqrts")])
-\f
-;;- arithmetic shift instructions
+
+
+;; Arithmetic shift instructions.
(define_insn "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
return "srlx\t%1, %2, %0";
}
[(set_attr "type" "shift")])
-\f
-;; Unconditional and other jump instructions
+
+
+;; Unconditional and other jump instructions.
+
(define_insn "jump"
[(set (pc) (label_ref (match_operand 0 "" "")))]
""
"jmp\t%a0%#"
[(set_attr "type" "uncond_branch")])
-;;- jump to subroutine
+
+;; Jump to subroutine instructions.
+
(define_expand "call"
;; Note that this expression is not used for generating RTL.
;; All the RTL is generated explicitly below.
DONE;
})
-;;- tail calls
+;; Tail call instructions.
+
(define_expand "sibcall"
[(parallel [(call (match_operand 0 "call_operand" "") (const_int 0))
(return)])]
"* return output_sibcall(insn, operands[1]);"
[(set_attr "type" "sibcall")])
-(define_expand "sibcall_epilogue"
- [(return)]
- ""
-{
- sparc_expand_epilogue ();
- DONE;
-})
+
+;; Special instructions.
(define_expand "prologue"
[(const_int 0)]
sparc_expand_epilogue ();
})
+(define_expand "sibcall_epilogue"
+ [(return)]
+ ""
+{
+ sparc_expand_epilogue ();
+ DONE;
+})
+
(define_expand "return"
[(return)]
"sparc_can_use_return_insn_p ()"
{ return TARGET_V9 ? "flush\t%f0" : "iflush\t%f0"; }
[(set_attr "type" "iflush")])
-\f
-;; find first set.
+
+;; Find first set instructions.
;; The scan instruction searches from the most significant bit while ffs
;; searches from the least significant bit. The bit index and treatment of
(compare:CCX (match_dup 1) (const_int 0)))])]
"")
+
+;; Prefetch instructions.
+
;; ??? UltraSPARC-III note: A memory operation loading into the floating point register
;; ??? file, if it hits the prefetch cache, has a chance to dual-issue with other memory
;; ??? operations. With DFA we might be able to model this, but it requires a lot of
return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
}
[(set_attr "type" "load")])
-\f
+
+
+;; Trap instructions.
+
(define_insn "trap"
[(trap_if (const_int 1) (const_int 5))]
""
"t%C0\t%%xcc, %1"
[(set_attr "type" "trap")])
-;; TLS support
+
+;; TLS support instructions.
+
(define_insn "tgd_hi22"
[(set (match_operand:SI 0 "register_operand" "=r")
(high:SI (unspec:SI [(match_operand 1 "tgd_symbolic_operand" "")]
"stx\t%0, [%1 + %2], %%tldo_add(%3)"
[(set_attr "type" "store")])
+
;; Vector instructions.
(define_insn "addv2si3"