diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c6b3bc2d54a..8eed4352938 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +2005-07-26 Aldy Hernandez + + * 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_): New. + (builtin_write_): New. + (builtin_write64): New. + (optional_membar_): New. + 2005-07-26 J"orn Rennecke * emit-rtl.c (gen_lowpart_common): Compare size of MODE in bits diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c index 9b94bd3ddbb..756ae633293 100644 --- a/gcc/config/frv/frv.c +++ b/gcc/config/frv/frv.c @@ -7953,6 +7953,35 @@ static struct builtin_description bdesc_voidacc[] = { 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 @@ -7968,6 +7997,8 @@ frv_init_builtins (void) 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) \ @@ -8034,6 +8065,12 @@ frv_init_builtins (void) 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); @@ -8139,6 +8176,15 @@ frv_init_builtins (void) 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 @@ -8364,6 +8410,18 @@ frv_legitimize_argument (enum insn_code icode, int opnum, rtx arg) 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. */ @@ -8612,6 +8670,39 @@ frv_expand_voidaccop_builtin (enum insn_code icode, tree arglist) 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, @@ -8956,6 +9047,14 @@ frv_expand_builtin (tree exp, 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; } diff --git a/gcc/config/frv/frv.h b/gcc/config/frv/frv.h index b33805c0a1a..41c11c4feee 100644 --- a/gcc/config/frv/frv.h +++ b/gcc/config/frv/frv.h @@ -2985,7 +2985,15 @@ enum frv_builtins FRV_BUILTIN_IACCreadl, FRV_BUILTIN_IACCsetll, FRV_BUILTIN_IACCsetl, - FRV_BUILTIN_SCAN + 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 diff --git a/gcc/config/frv/frv.md b/gcc/config/frv/frv.md index b8c37c51ed3..5b744bbc523 100644 --- a/gcc/config/frv/frv.md +++ b/gcc/config/frv/frv.md @@ -41,6 +41,9 @@ (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,7 +89,9 @@ (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,7 +2167,45 @@ else FAIL; }") + +;; The load part of a __builtin_read* function. +;; Use UNSPECs to distinguish these patterns from normal moves. +(define_insn "builtin_read_" + [(set (match_operand:SI 0 "register_operand" "=d") + (zero_extend:SI (unspec:IMODE + [(match_operand:IMODE 1 "memory_operand" "m")] + UNSPEC_BUILTIN_LOAD)))] + "" + "ld%I1%U1 %M1,%0" + [(set_attr "length" "4") + (set_attr "type" "gload")]) +;; The store part of a __builtin_write* function. +(define_insn "builtin_write_" + [(set (match_operand:IMODE 0 "memory_operand" "=m") + (unspec:IMODE [(match_operand:IMODE 1 "reg_or_0_operand" "dO")] + UNSPEC_BUILTIN_STORE))] + "" + "st%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_" + [(set (match_operand:IMODE 0 "memory_operand" "=m") + (unspec:IMODE [(const_int 0)] UNSPEC_OPTIONAL_MEMBAR))] + "" + "membar" + [(set_attr "length" "4")]) ;; :::::::::::::::::::: ;; :: diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 7e137950065..dc02b62ae7a 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -6044,6 +6044,7 @@ here in tabular form. * Argument Types:: * Directly-mapped Integer Functions:: * Directly-mapped Media Functions:: +* Raw read/write Functions:: * Other Built-in Functions:: @end menu @@ -6398,6 +6399,27 @@ The functions listed below map directly to FR-V M-type instructions. @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 diff --git a/gcc/testsuite/gcc.target/frv/all-builtin-read16.c b/gcc/testsuite/gcc.target/frv/all-builtin-read16.c new file mode 100644 index 00000000000..362cc8468e0 --- /dev/null +++ b/gcc/testsuite/gcc.target/frv/all-builtin-read16.c @@ -0,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" } } */ diff --git a/gcc/testsuite/gcc.target/frv/all-builtin-read32.c b/gcc/testsuite/gcc.target/frv/all-builtin-read32.c new file mode 100644 index 00000000000..7e988a4378f --- /dev/null +++ b/gcc/testsuite/gcc.target/frv/all-builtin-read32.c @@ -0,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" } } */ diff --git a/gcc/testsuite/gcc.target/frv/all-builtin-read64.c b/gcc/testsuite/gcc.target/frv/all-builtin-read64.c new file mode 100644 index 00000000000..1d5b6562a4a --- /dev/null +++ b/gcc/testsuite/gcc.target/frv/all-builtin-read64.c @@ -0,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" } } */ diff --git a/gcc/testsuite/gcc.target/frv/all-builtin-read8.c b/gcc/testsuite/gcc.target/frv/all-builtin-read8.c new file mode 100644 index 00000000000..b53fb61797d --- /dev/null +++ b/gcc/testsuite/gcc.target/frv/all-builtin-read8.c @@ -0,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" } } */ diff --git a/gcc/testsuite/gcc.target/frv/all-builtin-write16.c b/gcc/testsuite/gcc.target/frv/all-builtin-write16.c new file mode 100644 index 00000000000..f9f1cb517ee --- /dev/null +++ b/gcc/testsuite/gcc.target/frv/all-builtin-write16.c @@ -0,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" } } */ diff --git a/gcc/testsuite/gcc.target/frv/all-builtin-write32.c b/gcc/testsuite/gcc.target/frv/all-builtin-write32.c new file mode 100644 index 00000000000..b97715313c7 --- /dev/null +++ b/gcc/testsuite/gcc.target/frv/all-builtin-write32.c @@ -0,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" } } */ diff --git a/gcc/testsuite/gcc.target/frv/all-builtin-write64.c b/gcc/testsuite/gcc.target/frv/all-builtin-write64.c new file mode 100644 index 00000000000..eac50a266c7 --- /dev/null +++ b/gcc/testsuite/gcc.target/frv/all-builtin-write64.c @@ -0,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" } } */ diff --git a/gcc/testsuite/gcc.target/frv/all-builtin-write8.c b/gcc/testsuite/gcc.target/frv/all-builtin-write8.c new file mode 100644 index 00000000000..56e4f3e41b5 --- /dev/null +++ b/gcc/testsuite/gcc.target/frv/all-builtin-write8.c @@ -0,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" } } */