Index: gcc/c-family/c-format.c
===================================================================
--- gcc/c-family/c-format.c	(revision 212900)
+++ gcc/c-family/c-format.c	(working copy)
@@ -637,8 +637,9 @@
   { "I",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
   { "L",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
   { "U",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
-  { "r",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "",  "", NULL },
-  { "@",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
+#ifdef ASM_FPRINTF_TABLE
+  ASM_FPRINTF_TABLE
+#endif
   { NULL,  0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
 };
 
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h	(revision 212900)
+++ gcc/config/arm/arm.h	(working copy)
@@ -888,6 +888,12 @@
     fputs (reg_names [va_arg (ARGS, int)], FILE);	\
     break;
 
+/* Used in c-format.c to add entries to the table used to validate calls 
+   to asm_fprintf. */
+#define ASM_FPRINTF_TABLE \
+  { "r",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "",  "", NULL }, \
+  { "@",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
+
 /* Round X up to the nearest word.  */
 #define ROUND_UP_WORD(X) (((X) + 3) & ~3)
 
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 212900)
+++ gcc/doc/tm.texi	(working copy)
@@ -8611,8 +8611,39 @@
 The varargs input pointer is @var{argptr} and the rest of the format
 string, starting the character after the one that is being switched
 upon, is pointed to by @var{format}.
+See also ASM_FPRINTF_TABLE.
+
+Example:
+@smallexample
+#define ASM_FPRINTF_EXTENSIONS(FILE, ARGS, P)		\
+  case '@':						\
+    fputs (ASM_COMMENT_START, FILE);			\
+    break;						\
+							\
+  case 'r':						\
+    fputs (REGISTER_PREFIX, FILE);			\
+    fputs (reg_names [va_arg (ARGS, int)], FILE);	\
+    break;
+@end smallexample
 @end defmac
 
+@defmac ASM_FPRINTF_TABLE
+When using ASM_FPRINTF_EXTENSIONS, you must also use this macro to define
+table entries for the printf format checking performed in c-format.c. 
+This macro must contain format_char_info entries for each printf format 
+being added.
+
+Example:
+@smallexample
+#define ASM_FPRINTF_TABLE \
+  @{ "r", 0, STD_C89, \
+     @{ T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, \
+      BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN @}, \
+  "", "", NULL @}, \
+  @{ "@",   0, STD_C89, NOARGUMENTS, "",      "",   NULL @},
+@end smallexample
+@end defmac
+
 @defmac ASSEMBLER_DIALECT
 If your target supports multiple dialects of assembler language (such as
 different opcodes), define this macro as a C expression that gives the
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	(revision 212900)
+++ gcc/doc/tm.texi.in	(working copy)
@@ -6370,8 +6370,39 @@
 The varargs input pointer is @var{argptr} and the rest of the format
 string, starting the character after the one that is being switched
 upon, is pointed to by @var{format}.
+See also ASM_FPRINTF_TABLE.
+
+Example:
+@smallexample
+#define ASM_FPRINTF_EXTENSIONS(FILE, ARGS, P)		\
+  case '@':						\
+    fputs (ASM_COMMENT_START, FILE);			\
+    break;						\
+							\
+  case 'r':						\
+    fputs (REGISTER_PREFIX, FILE);			\
+    fputs (reg_names [va_arg (ARGS, int)], FILE);	\
+    break;
+@end smallexample
 @end defmac
 
+@defmac ASM_FPRINTF_TABLE
+When using ASM_FPRINTF_EXTENSIONS, you must also use this macro to define
+table entries for the printf format checking performed in c-format.c. 
+This macro must contain format_char_info entries for each printf format 
+being added.
+
+Example:
+@smallexample
+#define ASM_FPRINTF_TABLE \
+  @{ "r", 0, STD_C89, \
+     @{ T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, \
+      BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN @}, \
+  "", "", NULL @}, \
+  @{ "@",   0, STD_C89, NOARGUMENTS, "",      "",   NULL @},
+@end smallexample
+@end defmac
+
 @defmac ASSEMBLER_DIALECT
 If your target supports multiple dialects of assembler language (such as
 different opcodes), define this macro as a C expression that gives the
Index: gcc/testsuite/gcc.dg/format/asm_fprintf-1.c
===================================================================
--- gcc/testsuite/gcc.dg/format/asm_fprintf-1.c	(revision 212900)
+++ gcc/testsuite/gcc.dg/format/asm_fprintf-1.c	(working copy)
@@ -37,10 +37,14 @@
   asm_fprintf ("%d %lu\n", i, ul);
 
   /* Extensions provided in asm_fprintf.  */
-  asm_fprintf ("%O%R%I%L%U%@");
-  asm_fprintf ("%r", i);
+  asm_fprintf ("%O%R%I%L%U");
   asm_fprintf ("%wd%wi%wo%wu%wx%wX", ll, ll, ull, ull, ull, ull);
 
+  /* These 2 format specifiers are only available on arm. */
+#ifdef __arm__
+  asm_fprintf("%@%r", i);
+#endif
+
   /* Standard specifiers not accepted in asm_fprintf.  */
   asm_fprintf ("%f\n", d); /* { dg-warning "format" "float" } */
   asm_fprintf ("%e\n", d); /* { dg-warning "format" "float" } */
