📄 sparc.md
字号:
;; Machine description for SPARC chip for GCC;; Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,;; 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.;; Contributed by Michael Tiemann (tiemann@cygnus.com);; 64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,;; at Cygnus Support.;; This file is part of GCC.;; GCC is free software; you can redistribute it and/or modify;; it under the terms of the GNU General Public License as published by;; the Free Software Foundation; either version 2, or (at your option);; any later version.;; GCC is distributed in the hope that it will be useful,;; but WITHOUT ANY WARRANTY; without even the implied warranty of;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the;; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License;; along with GCC; see the file COPYING. If not, write to;; the Free Software Foundation, 59 Temple Place - Suite 330,;; Boston, MA 02111-1307, USA.;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.(define_constants [(UNSPEC_MOVE_PIC 0) (UNSPEC_UPDATE_RETURN 1) (UNSPEC_GET_PC 2) (UNSPEC_MOVE_PIC_LABEL 5) (UNSPEC_SETH44 6) (UNSPEC_SETM44 7) (UNSPEC_SETHH 9) (UNSPEC_SETLM 10) (UNSPEC_EMB_HISUM 11) (UNSPEC_EMB_TEXTUHI 13) (UNSPEC_EMB_TEXTHI 14) (UNSPEC_EMB_TEXTULO 15) (UNSPEC_EMB_SETHM 18) (UNSPEC_TLSGD 30) (UNSPEC_TLSLDM 31) (UNSPEC_TLSLDO 32) (UNSPEC_TLSIE 33) (UNSPEC_TLSLE 34) (UNSPEC_TLSLD_BASE 35) ])(define_constants [(UNSPECV_BLOCKAGE 0) (UNSPECV_FLUSHW 1) (UNSPECV_GOTO 2) (UNSPECV_GOTO_V9 3) (UNSPECV_FLUSH 4) (UNSPECV_SETJMP 5) ]);; 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" "v7, cypress, v8, supersparc, sparclite,f930,f934, hypersparc,sparclite86x, sparclet,tsc701, v9, ultrasparc, ultrasparc3" (const (symbol_ref "sparc_cpu_attr")));; Attribute for the instruction set.;; At present we only need to distinguish v9/!v9, but for clarity we;; test TARGET_V8 too.(define_attr "isa" "v6,v8,v9,sparclet" (const (cond [(symbol_ref "TARGET_V9") (const_string "v9") (symbol_ref "TARGET_V8") (const_string "v8") (symbol_ref "TARGET_SPARCLET") (const_string "sparclet")] (const_string "v6"))));; Architecture size.(define_attr "arch" "arch32bit,arch64bit" (const (cond [(symbol_ref "TARGET_ARCH64") (const_string "arch64bit")] (const_string "arch32bit"))));; Insn type.(define_attr "type" "ialu,compare,shift, load,sload,store, uncond_branch,branch,call,sibcall,call_no_delay_slot, imul,idiv, fpload,fpstore, fp,fpmove, fpcmove,fpcrmove, fpcmp, fpmul,fpdivs,fpdivd, fpsqrts,fpsqrtd, fga,fgm_pack,fgm_mul,fgm_pdist,fgm_cmp, cmove, ialuX, multi,flushw,iflush,trap" (const_string "ialu"));; true if branch/call has empty delay slot and will emit a nop in it(define_attr "empty_delay_slot" "false,true" (symbol_ref "empty_delay_slot (insn)"))(define_attr "branch_type" "none,icc,fcc,reg" (const_string "none"))(define_attr "pic" "false,true" (symbol_ref "flag_pic != 0"))(define_attr "current_function_calls_alloca" "false,true" (symbol_ref "current_function_calls_alloca != 0"))(define_attr "flat" "false,true" (symbol_ref "TARGET_FLAT != 0"));; Length (in # of insns).;; Beware that setting a length greater or equal to 3 for conditional branches;; has a side-effect (see output_cbranch and output_v9branch).(define_attr "length" "" (cond [(eq_attr "type" "uncond_branch,call,sibcall") (if_then_else (eq_attr "empty_delay_slot" "true") (const_int 2) (const_int 1)) (eq_attr "branch_type" "icc") (if_then_else (match_operand 0 "noov_compare64_op" "") (if_then_else (lt (pc) (match_dup 1)) (if_then_else (lt (minus (match_dup 1) (pc)) (const_int 260000)) (if_then_else (eq_attr "empty_delay_slot" "true") (const_int 2) (const_int 1)) (if_then_else (eq_attr "empty_delay_slot" "true") (const_int 4) (const_int 3))) (if_then_else (lt (minus (pc) (match_dup 1)) (const_int 260000)) (if_then_else (eq_attr "empty_delay_slot" "true") (const_int 2) (const_int 1)) (if_then_else (eq_attr "empty_delay_slot" "true") (const_int 4) (const_int 3)))) (if_then_else (eq_attr "empty_delay_slot" "true") (const_int 2) (const_int 1))) (eq_attr "branch_type" "fcc") (if_then_else (match_operand 0 "fcc0_reg_operand" "") (if_then_else (eq_attr "empty_delay_slot" "true") (if_then_else (eq (symbol_ref "TARGET_V9") (const_int 0)) (const_int 3) (const_int 2)) (if_then_else (eq (symbol_ref "TARGET_V9") (const_int 0)) (const_int 2) (const_int 1))) (if_then_else (lt (pc) (match_dup 2)) (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 260000)) (if_then_else (eq_attr "empty_delay_slot" "true") (const_int 2) (const_int 1)) (if_then_else (eq_attr "empty_delay_slot" "true") (const_int 4) (const_int 3))) (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 260000)) (if_then_else (eq_attr "empty_delay_slot" "true") (const_int 2) (const_int 1)) (if_then_else (eq_attr "empty_delay_slot" "true") (const_int 4) (const_int 3))))) (eq_attr "branch_type" "reg") (if_then_else (lt (pc) (match_dup 2)) (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 32000)) (if_then_else (eq_attr "empty_delay_slot" "true") (const_int 2) (const_int 1)) (if_then_else (eq_attr "empty_delay_slot" "true") (const_int 4) (const_int 3))) (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 32000)) (if_then_else (eq_attr "empty_delay_slot" "true") (const_int 2) (const_int 1)) (if_then_else (eq_attr "empty_delay_slot" "true") (const_int 4) (const_int 3)))) ] (const_int 1)));; FP precision.(define_attr "fptype" "single,double" (const_string "single"));; UltraSPARC-III integer load type.(define_attr "us3load_type" "2cycle,3cycle" (const_string "2cycle"))(define_asm_attributes [(set_attr "length" "2") (set_attr "type" "multi")]);; Attributes for instruction and branch scheduling(define_attr "tls_call_delay" "false,true" (symbol_ref "tls_call_delay (insn)"))(define_attr "in_call_delay" "false,true" (cond [(eq_attr "type" "uncond_branch,branch,call,sibcall,call_no_delay_slot,multi") (const_string "false") (eq_attr "type" "load,fpload,store,fpstore") (if_then_else (eq_attr "length" "1") (const_string "true") (const_string "false"))] (if_then_else (and (eq_attr "length" "1") (eq_attr "tls_call_delay" "true")) (const_string "true") (const_string "false"))))(define_delay (eq_attr "type" "call") [(eq_attr "in_call_delay" "true") (nil) (nil)])(define_attr "eligible_for_sibcall_delay" "false,true" (symbol_ref "eligible_for_sibcall_delay (insn)"))(define_delay (eq_attr "type" "sibcall") [(eq_attr "eligible_for_sibcall_delay" "true") (nil) (nil)])(define_attr "leaf_function" "false,true" (const (symbol_ref "current_function_uses_only_leaf_regs")));; ??? Should implement the notion of predelay slots for floating point;; branches. This would allow us to remove the nop always inserted before;; a floating point branch.;; ??? It is OK for fill_simple_delay_slots to put load/store instructions;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so.;; This is because doing so will add several pipeline stalls to the path;; that the load/store did not come from. Unfortunately, there is no way;; to prevent fill_eager_delay_slots from using load/store without completely;; disabling them. For the SPEC benchmark set, this is a serious lose,;; because it prevents us from moving back the final store of inner loops.(define_attr "in_branch_delay" "false,true" (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,sibcall,call_no_delay_slot,multi") (eq_attr "length" "1")) (const_string "true") (const_string "false")))(define_attr "in_uncond_branch_delay" "false,true" (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,sibcall,call_no_delay_slot,multi") (eq_attr "length" "1")) (const_string "true") (const_string "false")))(define_attr "in_annul_branch_delay" "false,true" (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,sibcall,call_no_delay_slot,multi") (eq_attr "length" "1")) (const_string "true") (const_string "false")))(define_delay (eq_attr "type" "branch") [(eq_attr "in_branch_delay" "true") (nil) (eq_attr "in_annul_branch_delay" "true")])(define_delay (eq_attr "type" "uncond_branch") [(eq_attr "in_uncond_branch_delay" "true") (nil) (nil)]) ;; Include SPARC DFA schedulers(include "cypress.md")(include "supersparc.md")(include "hypersparc.md")(include "sparclet.md")(include "ultra1_2.md")(include "ultra3.md");; Compare instructions.;; This controls RTL generation and register allocation.;; We generate RTL for comparisons and branches by having the cmpxx ;; patterns store away the operands. Then, the scc and bcc patterns;; emit RTL for both the compare and the branch.;;;; We do this because we want to generate different code for an sne and;; seq insn. In those cases, if the second operand of the compare is not;; const0_rtx, we want to compute the xor of the two operands and test;; it against zero.;;;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match;; 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" "") (match_operand:SI 1 "arith_operand" "")))] ""{ if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx) operands[0] = force_reg (SImode, operands[0]); sparc_compare_op0 = operands[0]; sparc_compare_op1 = operands[1]; DONE;})(define_expand "cmpdi" [(set (reg:CCX 100) (compare:CCX (match_operand:DI 0 "compare_operand" "") (match_operand:DI 1 "arith_double_operand" "")))] "TARGET_ARCH64"{ if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx) operands[0] = force_reg (DImode, operands[0]); sparc_compare_op0 = operands[0]; sparc_compare_op1 = operands[1]; DONE;})(define_expand "cmpsf" ;; The 96 here isn't ever used by anyone. [(set (reg:CCFP 96) (compare:CCFP (match_operand:SF 0 "register_operand" "") (match_operand:SF 1 "register_operand" "")))] "TARGET_FPU"{ sparc_compare_op0 = operands[0]; sparc_compare_op1 = operands[1]; DONE;})(define_expand "cmpdf" ;; The 96 here isn't ever used by anyone. [(set (reg:CCFP 96) (compare:CCFP (match_operand:DF 0 "register_operand" "") (match_operand:DF 1 "register_operand" "")))] "TARGET_FPU"{ sparc_compare_op0 = operands[0]; sparc_compare_op1 = operands[1]; DONE;})(define_expand "cmptf" ;; The 96 here isn't ever used by anyone. [(set (reg:CCFP 96) (compare:CCFP (match_operand:TF 0 "register_operand" "") (match_operand:TF 1 "register_operand" "")))] "TARGET_FPU"{ sparc_compare_op0 = operands[0]; sparc_compare_op1 = operands[1]; DONE;});; Now the compare DEFINE_INSNs.(define_insn "*cmpsi_insn" [(set (reg:CC 100) (compare:CC (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "arith_operand" "rI")))] "" "cmp\t%0, %1" [(set_attr "type" "compare")])(define_insn "*cmpdi_sp64" [(set (reg:CCX 100) (compare:CCX (match_operand:DI 0 "register_operand" "r") (match_operand:DI 1 "arith_double_operand" "rHI")))] "TARGET_ARCH64" "cmp\t%0, %1" [(set_attr "type" "compare")])(define_insn "*cmpsf_fpe" [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c") (compare:CCFPE (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] "TARGET_FPU"{ if (TARGET_V9) return "fcmpes\t%0, %1, %2"; return "fcmpes\t%1, %2";} [(set_attr "type" "fpcmp")])(define_insn "*cmpdf_fpe" [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c") (compare:CCFPE (match_operand:DF 1 "register_operand" "e") (match_operand:DF 2 "register_operand" "e")))] "TARGET_FPU"{ if (TARGET_V9) return "fcmped\t%0, %1, %2"; return "fcmped\t%1, %2";} [(set_attr "type" "fpcmp") (set_attr "fptype" "double")])(define_insn "*cmptf_fpe" [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c") (compare:CCFPE (match_operand:TF 1 "register_operand" "e") (match_operand:TF 2 "register_operand" "e")))] "TARGET_FPU && TARGET_HARD_QUAD"{ if (TARGET_V9) return "fcmpeq\t%0, %1, %2"; return "fcmpeq\t%1, %2";} [(set_attr "type" "fpcmp")])(define_insn "*cmpsf_fp" [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c") (compare:CCFP (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] "TARGET_FPU"{ if (TARGET_V9) return "fcmps\t%0, %1, %2"; return "fcmps\t%1, %2";} [(set_attr "type" "fpcmp")])(define_insn "*cmpdf_fp" [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c") (compare:CCFP (match_operand:DF 1 "register_operand" "e") (match_operand:DF 2 "register_operand" "e")))] "TARGET_FPU"{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -