This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
patch: frv __builtin_{read,write}* implementation
- From: Aldy Hernandez <aldyh at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 26 Jul 2005 11:34:26 -0400
- Subject: patch: frv __builtin_{read,write}* implementation
Hi folks.
This patch implements the __builtin_read* and __builtin_write* builtins
for FRV. They are just like loads and stores, but generate MEMBAR
instructions to flush I/O system (if I understand correctly).
I would have preferred the builtins to be named something like
__builtin_frv_read* or __builtin_frv_membar_read*, but the ucLinux and
the Linux kernel already call the builtins as implemented here.
Tested on ppc64-linux x frv-elf.
Committed.
* doc/extend.texi (Raw read/write Functions): New section.
* testsuite/gcc.target/frv/all-builtin-read8.c: New.
* testsuite/gcc.target/frv/all-builtin-read16.c: New.
* testsuite/gcc.target/frv/all-builtin-read32.c: New.
* testsuite/gcc.target/frv/all-builtin-read64.c: New.
* testsuite/gcc.target/frv/all-builtin-write8.c: New.
* testsuite/gcc.target/frv/all-builtin-write16.c: New.
* testsuite/gcc.target/frv/all-builtin-write32.c: New.
* testsuite/gcc.target/frv/all-builtin-write64.c: New.
* config/frv/frv.c: Add bdesc_loads global.
Add bdesc_stores global.
(frv_init_builtins): Add support for __builtin_{read/write}*.
(frv_volatile_memref): New.
(frv_expand_load_builtin): New.
(frv_expand_store_builtin): New.
* config/frv/frv.h (frv_builtins): Add FRV_BUILTIN_SCAN,
FRV_BUILTIN_READ8, FRV_BUILTIN_READ16, FRV_BUILTIN_READ32,
FRV_BUILTIN_READ64, FRV_BUILTIN_WRITE8, FRV_BUILTIN_WRITE16,
FRV_BUILTIN_WRITE32, FRV_BUILTIN_WRITE64.
* config/frv/frv.md (unspecs): Add UNSPEC_BUILTIN_LOAD,
UNSPEC_BUILTIN_STORE, UNSPEC_OPTIONAL_MEMBAR.
(builtin_read_<mode>): New.
(builtin_write_<mode>): New.
(builtin_write64): New.
(optional_membar_<mode>): New.
Index: doc/extend.texi
===================================================================
RCS file: /cvs/uberbaum/gcc/doc/extend.texi,v
retrieving revision 1.257
diff -c -p -r1.257 extend.texi
*** doc/extend.texi 27 Jun 2005 12:17:35 -0000 1.257
--- doc/extend.texi 26 Jul 2005 15:28:44 -0000
*************** this attribute to work correctly.
*** 1879,1888 ****
@item interrupt
@cindex interrupt handler functions
! Use this attribute on the ARM, AVR, C4x, M32R/D and Xstormy16 ports to indicate
! that the specified function is an interrupt handler. The compiler will
! generate function entry and exit sequences suitable for use in an
! interrupt handler when this attribute is present.
Note, interrupt handlers for the Blackfin, m68k, H8/300, H8/300H, H8S, and
SH processors can be specified via the @code{interrupt_handler} attribute.
--- 1879,1888 ----
@item interrupt
@cindex interrupt handler functions
! Use this attribute on the ARM, AVR, C4x, M32R/D, MS1, and Xstormy16
! ports to indicate that the specified function is an interrupt handler.
! The compiler will generate function entry and exit sequences suitable
! for use in an interrupt handler when this attribute is present.
Note, interrupt handlers for the Blackfin, m68k, H8/300, H8/300H, H8S, and
SH processors can be specified via the @code{interrupt_handler} attribute.
*************** here in tabular form.
*** 6020,6025 ****
--- 6020,6026 ----
* Argument Types::
* Directly-mapped Integer Functions::
* Directly-mapped Media Functions::
+ * Raw read/write Functions::
* Other Built-in Functions::
@end menu
*************** The functions listed below map directly
*** 6374,6379 ****
--- 6375,6401 ----
@tab @code{MXOR @var{a},@var{b},@var{c}}
@end multitable
+ @node Raw read/write Functions
+ @subsubsection Raw read/write Functions
+
+ This sections describes built-in functions related to read and write
+ instructions to access memory. These functions generate
+ @code{membar} instructions to flush the I/O load and stores where
+ appropriate, as described in Fujitsu's manual described above.
+
+ @table @code
+
+ @item unsigned char __builtin_read8 (void *@var{data})
+ @item unsigned short __builtin_read16 (void *@var{data})
+ @item unsigned long __builtin_read32 (void *@var{data})
+ @item unsigned long long __builtin_read64 (void *@var{data})
+
+ @item void __builtin_write8 (void *@var{data}, unsigned char @var{datum})
+ @item void __builtin_write16 (void *@var{data}, unsigned short @var{datum})
+ @item void __builtin_write32 (void *@var{data}, unsigned long @var{datum})
+ @item void __builtin_write64 (void *@var{data}, unsigned long long @var{datum})
+ @end table
+
@node Other Built-in Functions
@subsubsection Other Built-in Functions
Index: testsuite/gcc.target/frv/all-builtin-read8.c
===================================================================
RCS file: testsuite/gcc.target/frv/all-builtin-read8.c
diff -N testsuite/gcc.target/frv/all-builtin-read8.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.target/frv/all-builtin-read8.c 26 Jul 2005 15:28:44 -0000
***************
*** 0 ****
--- 1,11 ----
+ /* { dg-do compile } */
+
+ unsigned char z;
+
+ void foo (void *x)
+ {
+ z = __builtin_read8 (x);
+ }
+
+ /* { dg-final { scan-assembler "ldub" } } */
+ /* { dg-final { scan-assembler "membar" } } */
Index: testsuite/gcc.target/frv/all-builtin-read16.c
===================================================================
RCS file: testsuite/gcc.target/frv/all-builtin-read16.c
diff -N testsuite/gcc.target/frv/all-builtin-read16.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.target/frv/all-builtin-read16.c 26 Jul 2005 15:28:44 -0000
***************
*** 0 ****
--- 1,11 ----
+ /* { dg-do compile } */
+
+ unsigned short z;
+
+ void foo (void *x)
+ {
+ z = __builtin_read16 (x);
+ }
+
+ /* { dg-final { scan-assembler "lduh" } } */
+ /* { dg-final { scan-assembler "membar" } } */
Index: testsuite/gcc.target/frv/all-builtin-read32.c
===================================================================
RCS file: testsuite/gcc.target/frv/all-builtin-read32.c
diff -N testsuite/gcc.target/frv/all-builtin-read32.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.target/frv/all-builtin-read32.c 26 Jul 2005 15:28:44 -0000
***************
*** 0 ****
--- 1,12 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O" } */
+
+ unsigned long z;
+
+ void foo (void *x)
+ {
+ z = __builtin_read32 (x);
+ }
+
+ /* { dg-final { scan-assembler "ld " } } */
+ /* { dg-final { scan-assembler "membar" } } */
Index: testsuite/gcc.target/frv/all-builtin-read64.c
===================================================================
RCS file: testsuite/gcc.target/frv/all-builtin-read64.c
diff -N testsuite/gcc.target/frv/all-builtin-read64.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.target/frv/all-builtin-read64.c 26 Jul 2005 15:28:44 -0000
***************
*** 0 ****
--- 1,11 ----
+ /* { dg-do compile } */
+
+ unsigned long long z;
+
+ void foo (void *x)
+ {
+ z = __builtin_read64 (x);
+ }
+
+ /* { dg-final { scan-assembler "ldd" } } */
+ /* { dg-final { scan-assembler "membar" } } */
Index: testsuite/gcc.target/frv/all-builtin-write8.c
===================================================================
RCS file: testsuite/gcc.target/frv/all-builtin-write8.c
diff -N testsuite/gcc.target/frv/all-builtin-write8.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.target/frv/all-builtin-write8.c 26 Jul 2005 15:28:44 -0000
***************
*** 0 ****
--- 1,12 ----
+ /* { dg-do compile } */
+
+ unsigned char *addr;
+ unsigned char datum;
+
+ void foo ()
+ {
+ __builtin_write8 (addr, datum);
+ }
+
+ /* { dg-final { scan-assembler "stb" } } */
+ /* { dg-final { scan-assembler "membar" } } */
Index: testsuite/gcc.target/frv/all-builtin-write16.c
===================================================================
RCS file: testsuite/gcc.target/frv/all-builtin-write16.c
diff -N testsuite/gcc.target/frv/all-builtin-write16.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.target/frv/all-builtin-write16.c 26 Jul 2005 15:28:44 -0000
***************
*** 0 ****
--- 1,12 ----
+ /* { dg-do compile } */
+
+ unsigned short *addr;
+ unsigned short datum;
+
+ void foo ()
+ {
+ __builtin_write16 (addr, datum);
+ }
+
+ /* { dg-final { scan-assembler "sth" } } */
+ /* { dg-final { scan-assembler "membar" } } */
Index: testsuite/gcc.target/frv/all-builtin-write32.c
===================================================================
RCS file: testsuite/gcc.target/frv/all-builtin-write32.c
diff -N testsuite/gcc.target/frv/all-builtin-write32.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.target/frv/all-builtin-write32.c 26 Jul 2005 15:28:44 -0000
***************
*** 0 ****
--- 1,12 ----
+ /* { dg-do compile } */
+
+ unsigned long *addr;
+ unsigned long datum;
+
+ void foo ()
+ {
+ __builtin_write32 (addr, datum);
+ }
+
+ /* { dg-final { scan-assembler "st " } } */
+ /* { dg-final { scan-assembler "membar" } } */
Index: testsuite/gcc.target/frv/all-builtin-write64.c
===================================================================
RCS file: testsuite/gcc.target/frv/all-builtin-write64.c
diff -N testsuite/gcc.target/frv/all-builtin-write64.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.target/frv/all-builtin-write64.c 26 Jul 2005 15:28:44 -0000
***************
*** 0 ****
--- 1,12 ----
+ /* { dg-do compile } */
+
+ unsigned long long *addr;
+ unsigned long long datum;
+
+ void foo ()
+ {
+ __builtin_write64 (addr, datum);
+ }
+
+ /* { dg-final { scan-assembler "std " } } */
+ /* { dg-final { scan-assembler "membar" } } */
Index: config/frv/frv.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/frv/frv.c,v
retrieving revision 1.93
diff -c -p -r1.93 frv.c
*** config/frv/frv.c 28 Jun 2005 19:56:03 -0000 1.93
--- config/frv/frv.c 26 Jul 2005 15:28:48 -0000
*************** static struct builtin_description bdesc_
*** 7953,7958 ****
--- 7953,7987 ----
{ CODE_FOR_mdasaccs, "__MDASACCS", FRV_BUILTIN_MDASACCS, 0, 0 }
};
+ /* Intrinsics that load a value and then issue a MEMBAR.
+ The FLAGS field is the icode for the membar. */
+
+ static struct builtin_description bdesc_loads[] =
+ {
+ { CODE_FOR_builtin_read_qi, "__builtin_read8", FRV_BUILTIN_READ8, 0,
+ CODE_FOR_optional_membar_qi },
+ { CODE_FOR_builtin_read_hi, "__builtin_read16", FRV_BUILTIN_READ16, 0,
+ CODE_FOR_optional_membar_hi },
+ { CODE_FOR_builtin_read_si, "__builtin_read32", FRV_BUILTIN_READ32, 0,
+ CODE_FOR_optional_membar_si },
+ { CODE_FOR_builtin_read_di, "__builtin_read64", FRV_BUILTIN_READ64, 0,
+ CODE_FOR_optional_membar_di }
+ };
+
+ /* Likewise stores. */
+
+ static struct builtin_description bdesc_stores[] =
+ {
+ { CODE_FOR_builtin_write_qi, "__builtin_write8", FRV_BUILTIN_WRITE8, 0,
+ CODE_FOR_optional_membar_qi },
+ { CODE_FOR_builtin_write_hi, "__builtin_write16", FRV_BUILTIN_WRITE16, 0,
+ CODE_FOR_optional_membar_hi },
+ { CODE_FOR_builtin_write_si, "__builtin_write32", FRV_BUILTIN_WRITE32, 0,
+ CODE_FOR_optional_membar_si },
+ { CODE_FOR_builtin_write64, "__builtin_write64", FRV_BUILTIN_WRITE64, 0,
+ CODE_FOR_optional_membar_di }
+ };
+
/* Initialize media builtins. */
static void
*************** frv_init_builtins (void)
*** 7968,7973 ****
--- 7997,8004 ----
tree sword2 = long_long_integer_type_node;
tree uword2 = long_long_unsigned_type_node;
tree uword4 = build_pointer_type (uword1);
+ tree vptr = build_pointer_type (build_type_variant (void_type_node, 0, 1));
+ tree ubyte = unsigned_char_type_node;
tree iacc = integer_type_node;
#define UNARY(RET, T1) \
*************** frv_init_builtins (void)
*** 8034,8039 ****
--- 8065,8076 ----
tree sw2_ftype_iacc = UNARY (sword2, iacc);
tree sw1_ftype_iacc = UNARY (sword1, iacc);
tree void_ftype_ptr = UNARY (voidt, const_ptr_type_node);
+ tree uw1_ftype_vptr = UNARY (uword1, vptr);
+ tree uw2_ftype_vptr = UNARY (uword2, vptr);
+ tree void_ftype_vptr_ub = BINARY (voidt, vptr, ubyte);
+ tree void_ftype_vptr_uh = BINARY (voidt, vptr, uhalf);
+ tree void_ftype_vptr_uw1 = BINARY (voidt, vptr, uword1);
+ tree void_ftype_vptr_uw2 = BINARY (voidt, vptr, uword2);
def_builtin ("__MAND", uw1_ftype_uw1_uw1, FRV_BUILTIN_MAND);
def_builtin ("__MOR", uw1_ftype_uw1_uw1, FRV_BUILTIN_MOR);
*************** frv_init_builtins (void)
*** 8139,8144 ****
--- 8176,8190 ----
def_builtin ("__IACCsetl", void_ftype_iacc_sw1, FRV_BUILTIN_IACCsetl);
def_builtin ("__data_prefetch0", void_ftype_ptr, FRV_BUILTIN_PREFETCH0);
def_builtin ("__data_prefetch", void_ftype_ptr, FRV_BUILTIN_PREFETCH);
+ def_builtin ("__builtin_read8", uw1_ftype_vptr, FRV_BUILTIN_READ8);
+ def_builtin ("__builtin_read16", uw1_ftype_vptr, FRV_BUILTIN_READ16);
+ def_builtin ("__builtin_read32", uw1_ftype_vptr, FRV_BUILTIN_READ32);
+ def_builtin ("__builtin_read64", uw2_ftype_vptr, FRV_BUILTIN_READ64);
+
+ def_builtin ("__builtin_write8", void_ftype_vptr_ub, FRV_BUILTIN_WRITE8);
+ def_builtin ("__builtin_write16", void_ftype_vptr_uh, FRV_BUILTIN_WRITE16);
+ def_builtin ("__builtin_write32", void_ftype_vptr_uw1, FRV_BUILTIN_WRITE32);
+ def_builtin ("__builtin_write64", void_ftype_vptr_uw2, FRV_BUILTIN_WRITE64);
#undef UNARY
#undef BINARY
*************** frv_legitimize_argument (enum insn_code
*** 8364,8369 ****
--- 8410,8427 ----
return copy_to_mode_reg (mode, arg);
}
+ /* Return a volatile memory reference of mode MODE whose address is ARG. */
+
+ static rtx
+ frv_volatile_memref (enum machine_mode mode, rtx arg)
+ {
+ rtx mem;
+
+ mem = gen_rtx_MEM (mode, memory_address (mode, arg));
+ MEM_VOLATILE_P (mem) = 1;
+ return mem;
+ }
+
/* Expand builtins that take a single, constant argument. At the moment,
only MHDSETS falls into this category. */
*************** frv_expand_voidaccop_builtin (enum insn_
*** 8612,8617 ****
--- 8670,8708 ----
return NULL_RTX;
}
+ /* Expand a __builtin_read* function. ICODE is the instruction code for
+ the load and MEMBAR_ICODE is the instruction code of the "membar". */
+
+ static rtx
+ frv_expand_load_builtin (enum insn_code icode, enum insn_code membar_icode,
+ tree arglist, rtx target)
+ {
+ rtx op0 = frv_read_argument (& arglist);
+
+ target = frv_legitimize_target (icode, target);
+ op0 = frv_volatile_memref (insn_data[membar_icode].operand[0].mode, op0);
+ emit_insn (GEN_FCN (icode) (target, op0));
+ emit_insn (GEN_FCN (membar_icode) (copy_rtx (op0)));
+ return target;
+ }
+
+ /* Likewise __builtin_write* functions, with ICODE being the instruction
+ code of the store. */
+
+ static rtx
+ frv_expand_store_builtin (enum insn_code icode, enum insn_code membar_icode,
+ tree arglist)
+ {
+ rtx op0 = frv_read_argument (& arglist);
+ rtx op1 = frv_read_argument (& arglist);
+
+ op0 = frv_volatile_memref (insn_data[membar_icode].operand[0].mode, op0);
+ op1 = frv_legitimize_argument (icode, 1, op1);
+ emit_insn (GEN_FCN (icode) (op0, op1));
+ emit_insn (GEN_FCN (membar_icode) (copy_rtx (op0)));
+ return NULL_RTX;
+ }
+
/* Expand the MDPACKH builtin. It takes four unsigned short arguments and
each argument forms one word of the two double-word input registers.
ARGLIST is a TREE_LIST of the arguments and TARGET, if nonnull,
*************** frv_expand_builtin (tree exp,
*** 8956,8961 ****
--- 9047,9060 ----
if (d->code == fcode)
return frv_expand_prefetches (d->icode, arglist);
+ for (i = 0, d = bdesc_loads; i < ARRAY_SIZE (bdesc_loads); i++, d++)
+ if (d->code == fcode)
+ return frv_expand_load_builtin (d->icode, d->flag, arglist, target);
+
+ for (i = 0, d = bdesc_stores; i < ARRAY_SIZE (bdesc_stores); i++, d++)
+ if (d->code == fcode)
+ return frv_expand_store_builtin (d->icode, d->flag, arglist);
+
return 0;
}
Index: config/frv/frv.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/frv/frv.h,v
retrieving revision 1.67
diff -c -p -r1.67 frv.h
*** config/frv/frv.h 26 Jun 2005 05:18:31 -0000 1.67
--- config/frv/frv.h 26 Jul 2005 15:28:51 -0000
*************** enum frv_builtins
*** 2985,2991 ****
FRV_BUILTIN_IACCreadl,
FRV_BUILTIN_IACCsetll,
FRV_BUILTIN_IACCsetl,
! FRV_BUILTIN_SCAN
};
#define FRV_BUILTIN_FIRST_NONMEDIA FRV_BUILTIN_SMUL
--- 2985,2999 ----
FRV_BUILTIN_IACCreadl,
FRV_BUILTIN_IACCsetll,
FRV_BUILTIN_IACCsetl,
! FRV_BUILTIN_SCAN,
! FRV_BUILTIN_READ8,
! FRV_BUILTIN_READ16,
! FRV_BUILTIN_READ32,
! FRV_BUILTIN_READ64,
! FRV_BUILTIN_WRITE8,
! FRV_BUILTIN_WRITE16,
! FRV_BUILTIN_WRITE32,
! FRV_BUILTIN_WRITE64
};
#define FRV_BUILTIN_FIRST_NONMEDIA FRV_BUILTIN_SMUL
Index: config/frv/frv.md
===================================================================
RCS file: /cvs/uberbaum/gcc/config/frv/frv.md,v
retrieving revision 1.37
diff -c -p -r1.37 frv.md
*** config/frv/frv.md 28 Jun 2005 19:56:04 -0000 1.37
--- config/frv/frv.md 26 Jul 2005 15:28:53 -0000
***************
*** 41,46 ****
--- 41,49 ----
(UNSPEC_EH_RETURN_EPILOGUE 6)
(UNSPEC_GOT 7)
(UNSPEC_LDD 8)
+ (UNSPEC_BUILTIN_LOAD 9)
+ (UNSPEC_BUILTIN_STORE 10)
+ (UNSPEC_OPTIONAL_MEMBAR 11)
(UNSPEC_GETTLSOFF 200)
(UNSPEC_TLS_LOAD_GOTTLSOFF12 201)
***************
*** 86,92 ****
(FDPIC_REG 15)
])
!
;; ::::::::::::::::::::
;; ::
--- 89,97 ----
(FDPIC_REG 15)
])
! (define_mode_macro IMODE [QI HI SI DI])
! (define_mode_attr IMODEsuffix [(QI "b") (HI "h") (SI "") (DI "d")])
! (define_mode_attr BREADsuffix [(QI "ub") (HI "uh") (SI "") (DI "d")])
;; ::::::::::::::::::::
;; ::
***************
*** 2162,2168 ****
--- 2167,2211 ----
else
FAIL;
}")
+
+ ;; The load part of a __builtin_read* function.
+ ;; Use UNSPECs to distinguish these patterns from normal moves.
+ (define_insn "builtin_read_<mode>"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extend:SI (unspec:IMODE
+ [(match_operand:IMODE 1 "memory_operand" "m")]
+ UNSPEC_BUILTIN_LOAD)))]
+ ""
+ "ld<BREADsuffix>%I1%U1 %M1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "gload")])
+
+ ;; The store part of a __builtin_write* function.
+ (define_insn "builtin_write_<mode>"
+ [(set (match_operand:IMODE 0 "memory_operand" "=m")
+ (unspec:IMODE [(match_operand:IMODE 1 "reg_or_0_operand" "dO")]
+ UNSPEC_BUILTIN_STORE))]
+ ""
+ "st<IMODEsuffix>%I0%U0 %z1, %M0"
+ [(set_attr "length" "4")
+ (set_attr "type" "gstore")])
+ ;; This one has a different predicate for operand 1.
+ (define_insn "builtin_write64"
+ [(set (match_operand:DI 0 "memory_operand" "=m")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "d")]
+ UNSPEC_BUILTIN_STORE))]
+ ""
+ "std%I0%U0 %z1, %M0"
+ [(set_attr "length" "4")
+ (set_attr "type" "gstore")])
+
+ (define_insn "optional_membar_<mode>"
+ [(set (match_operand:IMODE 0 "memory_operand" "=m")
+ (unspec:IMODE [(const_int 0)] UNSPEC_OPTIONAL_MEMBAR))]
+ ""
+ "membar"
+ [(set_attr "length" "4")])
;; ::::::::::::::::::::
;; ::