Index: gcc/target.def
===================================================================
--- gcc/target.def	2017-09-13 20:12:24.499190740 +0100
+++ gcc/target.def	2017-09-13 20:14:46.245761652 +0100
@@ -4573,6 +4573,16 @@ used for arguments without any special h
  default_function_arg_advance)
 
 DEFHOOK
+(function_arg_offset,
+ "This hook returns the number of bytes to add to the offset of an\n\
+argument of type @var{type} and mode @var{mode} when passed in memory.\n\
+This is needed for the SPU, which passes @code{char} and @code{short}\n\
+arguments in the preferred slot that is in the middle of the quad word\n\
+instead of starting at the top.  The default implementation returns 0.",
+ HOST_WIDE_INT, (machine_mode mode, const_tree type),
+ default_function_arg_offset)
+
+DEFHOOK
 (function_arg_padding,
  "This hook determines whether, and in which direction, to pad out\n\
 an argument of mode @var{mode} and type @var{type}.  It returns\n\
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	2017-09-13 18:03:51.114330107 +0100
+++ gcc/targhooks.h	2017-09-13 20:14:46.245761652 +0100
@@ -132,6 +132,7 @@ extern bool hook_bool_CUMULATIVE_ARGS_tr
   (const_tree, const_tree, const_tree);
 extern void default_function_arg_advance
   (cumulative_args_t, machine_mode, const_tree, bool);
+extern HOST_WIDE_INT default_function_arg_offset (machine_mode, const_tree);
 extern pad_direction default_function_arg_padding (machine_mode, const_tree);
 extern rtx default_function_arg
   (cumulative_args_t, machine_mode, const_tree, bool);
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2017-09-13 18:03:51.114330107 +0100
+++ gcc/targhooks.c	2017-09-13 20:14:46.245761652 +0100
@@ -734,6 +734,14 @@ default_function_arg_advance (cumulative
   gcc_unreachable ();
 }
 
+/* Default implementation of TARGET_FUNCTION_ARG_OFFSET.  */
+
+HOST_WIDE_INT
+default_function_arg_offset (machine_mode, const_tree)
+{
+  return 0;
+}
+
 /* Default implementation of TARGET_FUNCTION_ARG_PADDING: usually pad
    upward, but pad short args downward on big-endian machines.  */
 
Index: gcc/function.c
===================================================================
--- gcc/function.c	2017-09-13 20:12:24.498282217 +0100
+++ gcc/function.c	2017-09-13 20:14:46.244854334 +0100
@@ -4249,9 +4249,8 @@ locate_and_pad_parm (machine_mode passed
       locate->size.constant -= part_size_in_regs;
     }
 
-#ifdef FUNCTION_ARG_OFFSET
-  locate->offset.constant += FUNCTION_ARG_OFFSET (passed_mode, type);
-#endif
+  locate->offset.constant
+    += targetm.calls.function_arg_offset (passed_mode, type);
 }
 
 /* Round the stack offset in *OFFSET_PTR up to a multiple of BOUNDARY.
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	2017-09-13 20:12:24.496465170 +0100
+++ gcc/doc/tm.texi.in	2017-09-13 20:14:46.243947015 +0100
@@ -3281,13 +3281,7 @@ argument @var{libname} exists for symmet
 
 @hook TARGET_FUNCTION_ARG_ADVANCE
 
-@defmac FUNCTION_ARG_OFFSET (@var{mode}, @var{type})
-If defined, a C expression that is the number of bytes to add to the
-offset of the argument passed in memory.  This is needed for the SPU,
-which passes @code{char} and @code{short} arguments in the preferred
-slot that is in the middle of the quad word instead of starting at the
-top.
-@end defmac
+@hook TARGET_FUNCTION_ARG_OFFSET
 
 @hook TARGET_FUNCTION_ARG_PADDING
 
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2017-09-13 20:12:24.496465170 +0100
+++ gcc/doc/tm.texi	2017-09-13 20:14:46.243947015 +0100
@@ -4079,13 +4079,13 @@ on the stack.  The compiler knows how to
 used for arguments without any special help.
 @end deftypefn
 
-@defmac FUNCTION_ARG_OFFSET (@var{mode}, @var{type})
-If defined, a C expression that is the number of bytes to add to the
-offset of the argument passed in memory.  This is needed for the SPU,
-which passes @code{char} and @code{short} arguments in the preferred
-slot that is in the middle of the quad word instead of starting at the
-top.
-@end defmac
+@deftypefn {Target Hook} HOST_WIDE_INT TARGET_FUNCTION_ARG_OFFSET (machine_mode @var{mode}, const_tree @var{type})
+This hook returns the number of bytes to add to the offset of an
+argument of type @var{type} and mode @var{mode} when passed in memory.
+This is needed for the SPU, which passes @code{char} and @code{short}
+arguments in the preferred slot that is in the middle of the quad word
+instead of starting at the top.  The default implementation returns 0.
+@end deftypefn
 
 @deftypefn {Target Hook} pad_direction TARGET_FUNCTION_ARG_PADDING (machine_mode @var{mode}, const_tree @var{type})
 This hook determines whether, and in which direction, to pad out
Index: gcc/config/spu/spu.h
===================================================================
--- gcc/config/spu/spu.h	2017-09-13 20:12:24.493739600 +0100
+++ gcc/config/spu/spu.h	2017-09-13 20:14:46.241225060 +0100
@@ -309,13 +309,6 @@ #define CUMULATIVE_ARGS int
 #define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,FNDECL,N_NAMED_ARGS) \
 		((CUM) = 0)
 
-/* The SPU ABI wants 32/64-bit types at offset 0 in the quad-word on the
-   stack.  8/16-bit types should be at offsets 3/2 respectively.  */
-#define FUNCTION_ARG_OFFSET(MODE, TYPE)					\
-(((TYPE) && INTEGRAL_TYPE_P (TYPE) && GET_MODE_SIZE (MODE) < 4)		\
- ? (4 - GET_MODE_SIZE (MODE))						\
- : 0)
-
 #define PAD_VARARGS_DOWN 0
 
 #define FUNCTION_ARG_REGNO_P(N) ((N) >= (FIRST_ARG_REGNUM) && (N) <= (LAST_ARG_REGNUM))
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	2017-09-13 20:12:24.493739600 +0100
+++ gcc/config/spu/spu.c	2017-09-13 20:14:46.241225060 +0100
@@ -3881,6 +3881,18 @@ spu_function_arg_advance (cumulative_arg
 	   : spu_hard_regno_nregs (FIRST_ARG_REGNUM, mode));
 }
 
+/* Implement TARGET_FUNCTION_ARG_OFFSET.  The SPU ABI wants 32/64-bit
+   types at offset 0 in the quad-word on the stack.  8/16-bit types
+   should be at offsets 3/2 respectively.  */
+
+static HOST_WIDE_INT
+spu_function_arg_offset (machine_mode mode, const_tree type)
+{
+  if (type && INTEGRAL_TYPE_P (type) && GET_MODE_SIZE (mode) < 4)
+    return 4 - GET_MODE_SIZE (mode);
+  return 0;
+}
+
 /* Implement TARGET_FUNCTION_ARG_PADDING.  */
 
 static pad_direction
@@ -7300,6 +7312,9 @@ #define TARGET_FUNCTION_ARG spu_function
 #undef TARGET_FUNCTION_ARG_ADVANCE
 #define TARGET_FUNCTION_ARG_ADVANCE spu_function_arg_advance
 
+#undef TARGET_FUNCTION_ARG_OFFSET
+#define TARGET_FUNCTION_ARG_OFFSET spu_function_arg_offset
+
 #undef TARGET_FUNCTION_ARG_PADDING
 #define TARGET_FUNCTION_ARG_PADDING spu_function_arg_padding
 
Index: gcc/system.h
===================================================================
--- gcc/system.h	2017-09-13 20:12:24.498282217 +0100
+++ gcc/system.h	2017-09-13 20:14:46.244854334 +0100
@@ -915,7 +915,7 @@ #define realloc xrealloc
 	MODES_TIEABLE_P FUNCTION_ARG_PADDING SLOW_UNALIGNED_ACCESS	\
 	HARD_REGNO_NREGS SECONDARY_MEMORY_NEEDED_MODE			\
 	SECONDARY_MEMORY_NEEDED CANNOT_CHANGE_MODE_CLASS		\
-	TRULY_NOOP_TRUNCATION
+	TRULY_NOOP_TRUNCATION FUNCTION_ARG_OFFSET
 
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */
