OSDN Git Service

* sh.h (OVERRIDE_OPTIONS): Set default values for align_loops
[pf3gnuchains/gcc-fork.git] / gcc / config / sh / sh.md
index 45f6610..65dd696 100644 (file)
   (UNSPEC_NSB          17)
   (UNSPEC_ALLOCO       18)
   (UNSPEC_EH_RETURN    19)
+  (UNSPEC_TLSGD                20)
+  (UNSPEC_TLSLDM       21)
+  (UNSPEC_TLSIE                22)
+  (UNSPEC_DTPOFF       23)
+  (UNSPEC_GOTTPOFF     24)
+  (UNSPEC_TPOFF                25)
 
   ;; These are used with unspec_volatile.
   (UNSPECV_BLOCKAGE    0)
 ;; ftrc_s      fix_truncsfsi2_i4
 ;; dfdiv       double precision floating point divide (or square root)
 ;; cwb         ic_invalidate_line_i
+;; tls_load     load TLS related address 
 ;; arith_media SHmedia arithmetic, logical, and shift instructions
 ;; cbranch_media SHmedia conditional branch instructions
 ;; cmp_media   SHmedia compare instructions
 ;; fpconv_media        SHmedia single precision floating point conversions
 ;; fstore_media        SHmedia floating point register store instructions
 ;; gettr_media SHmedia gettr instruction
-;; invalidate_line_media SHmedia invaldiate_line sequence
+;; invalidate_line_media SHmedia invalidate_line sequence
 ;; jump_media  SHmedia unconditional branch instructions
 ;; load_media  SHmedia general register load instructions
 ;; pt_media    SHmedia pt instruction (expanded by assembler)
 ;; mcmp_media  SHmedia multimedia compare, absolute, saturating ops
 ;; mac_media   SHmedia mac-style fixed point operations
 ;; d2mpy_media SHmedia: two 32 bit integer multiplies
-;; atrans      SHmedia approximate transcendential functions
+;; atrans      SHmedia approximate transcendental functions
 ;; ustore_media        SHmedia unaligned stores
 ;; nil         no-op move, will be deleted.
 
 (define_attr "type"
- "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,fload,store,move,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fdiv,ftrc_s,dfp_arith,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,mem_fpscr,gp_fpscr,cwb,arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,d2mpy_media,atrans_media,ustore_media,nil,other"
+ "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,fload,store,move,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fdiv,ftrc_s,dfp_arith,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,mem_fpscr,gp_fpscr,cwb,tls_load,arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,d2mpy_media,atrans_media,ustore_media,nil,other"
   (const_string "other"))
 
 ;; We define a new attribute namely "insn_class".We use
         (eq_attr "type" "jump")
         (cond [(eq_attr "med_branch_p" "yes")
                (const_int 2)
-               (and (eq (symbol_ref "GET_CODE (PREV_INSN (insn))")
+               (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
                         (symbol_ref "INSN"))
-                    (eq (symbol_ref "INSN_CODE (PREV_INSN (insn))")
+                    (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
                         (symbol_ref "code_for_indirect_jump_scratch")))
                (if_then_else (eq_attr "braf_branch_p" "yes")
                              (const_int 6)
 ; the udivsi3 libcall has the same name, we must consider all registers
 ; clobbered that are in the union of the registers clobbered by the
 ; shmedia and the shcompact implementation.  Note, if the shcompact
-; implemenation actually used shcompact code, we'd need to clobber
+; implementation actually used shcompact code, we'd need to clobber
 ; also r23 and fr23.
 (define_insn "udivsi3_i1_media"
   [(set (match_operand:SI 0 "register_operand" "=z")
 ; the sdivsi3 libcall has the same name, we must consider all registers
 ; clobbered that are in the union of the registers clobbered by the
 ; shmedia and the shcompact implementation.  Note, if the shcompact
-; implemenation actually used shcompact code, we'd need to clobber
+; implementation actually used shcompact code, we'd need to clobber
 ; also r22, r23 and fr23.
 (define_insn "divsi3_i1_media"
   [(set (match_operand:SI 0 "register_operand" "=z")
 
 ;; This one has the additional purpose to record a possible scratch register
 ;; for the following branch.
+;; ??? Unfortunately, just setting the scratch register is not good enough,
+;; because the insn then might be deemed dead and deleted.  And we can't
+;; make the use in the jump insn explicit because that would disable
+;; delay slot scheduling from the target.
 (define_insn "indirect_jump_scratch"
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))]
+       (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR)) 
+   (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
   "TARGET_SH1"
   ""
   [(set_attr "length" "0")])
   [(set_attr "type" "jump")
    (set_attr "needs_delay_slot" "yes")])
 
+;; ??? It would be much saner to explicitly use the scratch register
+;; in the jump insn, and have indirect_jump_scratch only set it,
+;; but fill_simple_delay_slots would refuse to do delay slot filling
+;; from the target then, as it uses simplejump_p.
+;;(define_insn "jump_compact_far"
+;;  [(set (pc)
+;;     (label_ref (match_operand 0 "" "")))
+;;   (use (match_operand 1 "register_operand" "r")]
+;;  "TARGET_SH1"
+;;  "* return output_far_jump(insn, operands[0], operands[1]);"
+;;  [(set_attr "type" "jump")
+;;   (set_attr "needs_delay_slot" "yes")])
+
 (define_insn "jump_media"
   [(set (pc)
        (match_operand:DI 0 "target_operand" "b"))]
   ""
   "")
 
+;; TLS code generation.
+;; ??? this should be a define_insn_and_split
+;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
+;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
+;; for details.
+
+(define_insn "tls_global_dynamic"
+  [(set (match_operand:SI 0 "register_operand" "=&z")
+       (unspec:SI [(match_operand:SI 1 "" "")]
+                   UNSPEC_TLSGD))
+   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI PIC_REG))
+   (clobber (reg:SI PR_REG))
+   (clobber (scratch:SI))]
+  "TARGET_SH1"
+  "*
+{
+  return \"\\
+mov.l\\t1f,r4\\n\\
+\\tmova\\t2f,r0\\n\\
+\\tmov.l\\t2f,r1\\n\\
+\\tadd\\tr0,r1\\n\\
+\\tjsr\\t@r1\\n\\
+\\tadd\\tr12,r4\\n\\
+\\tbra\\t3f\\n\\
+\\tnop\\n\\
+\\t.align\\t2\\n\\
+1:\\t.long\\t%a1@TLSGD\\n\\
+2:\\t.long\\t__tls_get_addr@PLT\\n\\
+3:\";
+}"
+  [(set_attr "type" "tls_load")
+   (set_attr "length" "26")])
+
+(define_insn "tls_local_dynamic"
+  [(set (match_operand:SI 0 "register_operand" "=&z")
+       (unspec:SI [(match_operand:SI 1 "" "")]
+                   UNSPEC_TLSLDM))
+   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI PIC_REG))
+   (clobber (reg:SI PR_REG))
+   (clobber (scratch:SI))]
+  "TARGET_SH1"
+  "*
+{
+  return \"\\
+mov.l\\t1f,r4\\n\\
+\\tmova\\t2f,r0\\n\\
+\\tmov.l\\t2f,r1\\n\\
+\\tadd\\tr0,r1\\n\\
+\\tjsr\\t@r1\\n\\
+\\tadd\\tr12,r4\\n\\
+\\tbra\\t3f\\n\\
+\\tnop\\n\\
+\\t.align\\t2\\n\\
+1:\\t.long\\t%a1@TLSLDM\\n\\
+2:\\t.long\\t__tls_get_addr@PLT\\n\\
+3:\";
+}"
+  [(set_attr "type" "tls_load")
+   (set_attr "length" "26")])
+
+(define_expand "sym2DTPOFF"
+  [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
+  ""
+  "")
+
+(define_expand "symDTPOFF2reg"
+  [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
+  ""
+  "
+{
+  rtx dtpoffsym, insn;
+  rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
+
+  dtpoffsym = gen_sym2DTPOFF (operands[1]);
+  PUT_MODE (dtpoffsym, Pmode);
+  emit_move_insn (t, dtpoffsym);
+  insn = emit_move_insn (operands[0],
+                        gen_rtx_PLUS (Pmode, t, operands[2]));
+  DONE;
+}")
+
+(define_expand "sym2GOTTPOFF"
+  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
+  ""
+  "")
+
+(define_insn "tls_initial_exec"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+       (unspec:SI [(match_operand:SI 1 "" "")]
+                   UNSPEC_TLSIE))
+   (use (reg:SI GBR_REG))
+   (use (reg:SI PIC_REG))
+   (clobber (reg:SI R0_REG))]
+  ""
+  "*
+{
+  return \"\\
+mov.l\\t1f,r0\\n\\
+\\tstc\\tgbr,%0\\n\\
+\\tmov.l\\t@(r0,r12),r0\\n\\
+\\tbra\\t2f\\n\\
+\\tadd\\tr0,%0\\n\\
+\\t.align\\t2\\n\\
+1:\\t.long\\t%a1\\n\\
+2:\";
+}"
+  [(set_attr "type" "tls_load")
+   (set_attr "length" "16")])
+
+(define_expand "sym2TPOFF"
+  [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
+  ""
+  "")
+
+(define_expand "symTPOFF2reg"
+  [(match_operand 0 "" "") (match_operand 1 "" "")]
+  ""
+  "
+{
+  rtx tpoffsym, insn;
+
+  tpoffsym = gen_sym2TPOFF (operands[1]);
+  PUT_MODE (tpoffsym, Pmode);
+  insn = emit_move_insn (operands[0], tpoffsym);
+  DONE;
+}")
+
+(define_insn "load_gbr"
+  [(set (match_operand:SI 0 "register_operand" "") (reg:SI GBR_REG))
+   (use (reg:SI GBR_REG))]
+  ""
+  "stc gbr,%0"
+  [(set_attr "type" "tls_load")])
+
 ;; case instruction for switch statements.
 
 ;; Operand 0 is index
         (vec_concat:V2SF
          (vec_select:SF
           (match_dup 0)
-          (parallel [(not:BI (match_operand 4 "const_int_operand" "n"))]))
+          (parallel [(match_operand 7 "const_int_operand" "n")]))
          (match_operator:SF 3 "binary_float_operator"
            [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
                            (parallel [(match_operand 5
             (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
                            (parallel [(match_operand 6
                                        "const_int_operand" "n")]))]))
-        (parallel [(not:BI (match_dup 4)) (match_dup 4)])))]
-  "TARGET_SHMEDIA_FPU"
+        (parallel [(match_dup 7) (match_operand 4 "const_int_operand" "n")])))]
+  "TARGET_SHMEDIA_FPU && INTVAL (operands[4]) != INTVAL (operands[7])"
   "#"
-  "TARGET_SHMEDIA_FPU && reload_completed"
-  [(set (match_dup 7) (match_dup 8))]
+  "&& reload_completed"
+  [(set (match_dup 8) (match_dup 9))]
   "
 {
   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
                         (true_regnum (operands[2])
                          + (INTVAL (operands[6]) ^ endian)));
 
-  operands[7] = gen_rtx_REG (SFmode,
+  operands[8] = gen_rtx_REG (SFmode,
                             (true_regnum (operands[0])
                              + (INTVAL (operands[4]) ^ endian)));
-  operands[8] = gen_rtx (GET_CODE (operands[3]), SFmode, op1, op2);
+  operands[9] = gen_rtx (GET_CODE (operands[3]), SFmode, op1, op2);
 }"
   [(set_attr "type" "fparith_media")])
 
   "issue+load_store")
 
 ;; We don't model all pipeline stages; we model the issue ('D') stage
-;; inasmuch as we allow only two instructions to issue simultanously,
-;; and CO instructions prevent any simultanous issue of another instruction.
+;; inasmuch as we allow only two instructions to issue simultaneously,
+;; and CO instructions prevent any simultaneous issue of another instruction.
 ;; (This uses pipe_01 and pipe_02).
 ;; Double issue of EX insns is prevented by using the int unit in the EX stage.
 ;; Double issue of EX / BR insns is prevented by using the int unit /
 ;; (except in the cases outlined above), nor to describe the FS stage after
 ;; the F2 stage.
 
-;; Other MT  group intructions(1 step operations)
+;; Other MT  group instructions(1 step operations)
 ;; Group:      MT
 ;; Latency:    1
 ;; Issue Rate:         1