+2012-10-06 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/54760
+ * config/sh/sh.md (define_constants): Add UNSPECV_GBR.
+ (get_thread_pointer, set_thread_pointer): New expanders.
+ (load_gbr): Rename to store_gbr. Remove GBR_REG use.
+ (store_gbr): New insn.
+ * config/sh/sh.c (prepare_move_operands): Use gen_store_gbr instead of
+ gen_load_gbr in TLS_MODEL_LOCAL_EXEC case.
+ (sh1_builtin_p): New function.
+ (signature_args): Add SH_BLTIN_VP.
+ (bdesc): Add __builtin_thread_pointer and __builtin_set_thread_pointer.
+
2012-10-05 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
PR rtl-optimization/54739
case TLS_MODEL_LOCAL_EXEC:
tmp2 = gen_reg_rtx (Pmode);
- emit_insn (gen_load_gbr (tmp2));
+ emit_insn (gen_store_gbr (tmp2));
tmp = gen_reg_rtx (Pmode);
emit_insn (gen_symTPOFF2reg (tmp, op1));
return TARGET_SHMEDIA;
}
+static bool
+sh1_builtin_p (void)
+{
+ return TARGET_SH1;
+}
+
/* describe number and signedness of arguments; arg[0] == result
(1: unsigned, 2: signed, 4: don't care, 8: pointer 0: no argument */
/* 9: 64-bit pointer, 10: 32-bit pointer */
{ 1, 1, 1, 1 },
#define SH_BLTIN_PV 23
{ 0, 8 },
+#define SH_BLTIN_VP 24
+ { 8, 0 },
};
/* mcmv: operands considered unsigned. */
/* mmulsum_wq, msad_ubq: result considered unsigned long long. */
CODE_FOR_byterev, "__builtin_sh_media_BYTEREV", SH_BLTIN_2, 0 },
{ shmedia_builtin_p,
CODE_FOR_prefetch, "__builtin_sh_media_PREFO", SH_BLTIN_PSSV, 0 },
+
+ { sh1_builtin_p,
+ CODE_FOR_get_thread_pointer, "__builtin_thread_pointer", SH_BLTIN_VP, 0 },
+ { sh1_builtin_p,
+ CODE_FOR_set_thread_pointer, "__builtin_set_thread_pointer",
+ SH_BLTIN_PV, 0 },
};
static void
(UNSPECV_WINDOW_END 10)
(UNSPECV_CONST_END 11)
(UNSPECV_EH_RETURN 12)
+ (UNSPECV_GBR 13)
])
;; -------------------------------------------------------------------------
DONE;
})
-(define_insn "load_gbr"
- [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))
- (use (reg:SI GBR_REG))]
+;;------------------------------------------------------------------------------
+;; Thread pointer getter and setter.
+;;
+;; On SH the thread pointer is kept in the GBR.
+;; These patterns are usually expanded from the respective built-in functions.
+(define_expand "get_thread_pointer"
+ [(set (match_operand:SI 0 "register_operand") (reg:SI GBR_REG))]
+ "TARGET_SH1")
+
+;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses.
+(define_insn "store_gbr"
+ [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))]
""
"stc gbr,%0"
[(set_attr "type" "tls_load")])
+(define_expand "set_thread_pointer"
+ [(set (reg:SI GBR_REG)
+ (unspec_volatile:SI [(match_operand:SI 0 "register_operand")]
+ UNSPECV_GBR))]
+ "TARGET_SH1")
+
+(define_insn "load_gbr"
+ [(set (reg:SI GBR_REG)
+ (unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
+ UNSPECV_GBR))]
+ "TARGET_SH1"
+ "ldc %0,gbr"
+ [(set_attr "type" "move")])
+
+;;------------------------------------------------------------------------------
;; case instruction for switch statements.
;; Operand 0 is index
+2012-10-06 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/54760
+ * gcc.target/sh/pr54760-1.c: New.
+
2012-10-05 Jakub Jelinek <jakub@redhat.com>
* g++.dg/torture/Wsizeof-pointer-memaccess1.C: New test.
--- /dev/null
+/* Check that the __builtin_thread_pointer and __builtin_set_thread_pointer
+ built-in functions result in gbr store / load instructions. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
+/* { dg-final { scan-assembler-times "ldc" 1 } } */
+/* { dg-final { scan-assembler-times "stc" 1 } } */
+/* { dg-final { scan-assembler-times "gbr" 2 } } */
+
+void*
+test00 (void)
+{
+ return __builtin_thread_pointer ();
+}
+
+void
+test01 (void* p)
+{
+ __builtin_set_thread_pointer (p);
+}