/* Worker function for TARGET_CPU_CPP_BUILTINS. */
+static const char *const avr_builtin_name[] =
+ {
+#define DEF_BUILTIN(NAME, N_ARGS, ID, TYPE, CODE) NAME,
+#include "builtins.def"
+#undef DEF_BUILTIN
+ NULL
+ };
+
void
avr_cpu_cpp_builtins (struct cpp_reader *pfile)
{
+ int i;
+
builtin_define_std ("AVR");
if (avr_current_arch->macro)
if (!strcmp (lang_hooks.name, "GNU C"))
{
- int i;
-
for (i = 0; avr_addrspace[i].name; i++)
if (!ADDR_SPACE_GENERIC_P (i)
/* Only supply __FLASH<n> macro if the address space is reasonable
easily query if or if not a specific builtin
is available. */
- cpp_define (pfile, "__BUILTIN_AVR_NOP");
- cpp_define (pfile, "__BUILTIN_AVR_SEI");
- cpp_define (pfile, "__BUILTIN_AVR_CLI");
- cpp_define (pfile, "__BUILTIN_AVR_WDR");
- cpp_define (pfile, "__BUILTIN_AVR_SLEEP");
- cpp_define (pfile, "__BUILTIN_AVR_SWAP");
- cpp_define (pfile, "__BUILTIN_AVR_INSERT_BITS");
- cpp_define (pfile, "__BUILTIN_AVR_DELAY_CYCLES");
-
- cpp_define (pfile, "__BUILTIN_AVR_FMUL");
- cpp_define (pfile, "__BUILTIN_AVR_FMULS");
- cpp_define (pfile, "__BUILTIN_AVR_FMULSU");
-
- cpp_define (pfile, "__INT24_MAX__=8388607L");
- cpp_define (pfile, "__INT24_MIN__=(-__INT24_MAX__-1)");
- cpp_define (pfile, "__UINT24_MAX__=16777215UL");
+ for (i = 0; avr_builtin_name[i]; i++)
+ {
+ const char *name = avr_builtin_name[i];
+ char *Name = (char*) alloca (1 + strlen (name));
+
+ cpp_define (pfile, avr_toupper (Name, name));
+ }
}
enum avr_builtin_id
{
- AVR_BUILTIN_NOP,
- AVR_BUILTIN_SEI,
- AVR_BUILTIN_CLI,
- AVR_BUILTIN_WDR,
- AVR_BUILTIN_SLEEP,
- AVR_BUILTIN_SWAP,
- AVR_BUILTIN_INSERT_BITS,
- AVR_BUILTIN_FMUL,
- AVR_BUILTIN_FMULS,
- AVR_BUILTIN_FMULSU,
- AVR_BUILTIN_DELAY_CYCLES
+
+#define DEF_BUILTIN(NAME, N_ARGS, ID, TYPE, CODE) ID,
+#include "builtins.def"
+#undef DEF_BUILTIN
+
+ AVR_BUILTIN_COUNT
};
static void
(*lang_hooks.types.register_builtin_type) (uint24_type, "__uint24");
}
-#define DEF_BUILTIN(NAME, TYPE, CODE) \
- do \
- { \
- add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
- NULL, NULL_TREE); \
- } while (0)
-
-
/* Implement `TARGET_INIT_BUILTINS' */
/* Set up all builtin functions for this target. */
unsigned_char_type_node,
NULL_TREE);
- DEF_BUILTIN ("__builtin_avr_nop", void_ftype_void, AVR_BUILTIN_NOP);
- DEF_BUILTIN ("__builtin_avr_sei", void_ftype_void, AVR_BUILTIN_SEI);
- DEF_BUILTIN ("__builtin_avr_cli", void_ftype_void, AVR_BUILTIN_CLI);
- DEF_BUILTIN ("__builtin_avr_wdr", void_ftype_void, AVR_BUILTIN_WDR);
- DEF_BUILTIN ("__builtin_avr_sleep", void_ftype_void, AVR_BUILTIN_SLEEP);
- DEF_BUILTIN ("__builtin_avr_swap", uchar_ftype_uchar, AVR_BUILTIN_SWAP);
- DEF_BUILTIN ("__builtin_avr_delay_cycles", void_ftype_ulong,
- AVR_BUILTIN_DELAY_CYCLES);
-
- DEF_BUILTIN ("__builtin_avr_fmul", uint_ftype_uchar_uchar,
- AVR_BUILTIN_FMUL);
- DEF_BUILTIN ("__builtin_avr_fmuls", int_ftype_char_char,
- AVR_BUILTIN_FMULS);
- DEF_BUILTIN ("__builtin_avr_fmulsu", int_ftype_char_uchar,
- AVR_BUILTIN_FMULSU);
-
- DEF_BUILTIN ("__builtin_avr_insert_bits", uchar_ftype_ulong_uchar_uchar,
- AVR_BUILTIN_INSERT_BITS);
-
+#define DEF_BUILTIN(NAME, N_ARGS, ID, TYPE, CODE) \
+ add_builtin_function (NAME, TYPE, ID, BUILT_IN_MD, NULL, NULL_TREE);
+#include "builtins.def"
+#undef DEF_BUILTIN
+
avr_init_builtin_int24 ();
}
-#undef DEF_BUILTIN
struct avr_builtin_description
{
- const enum insn_code icode;
- const char *const name;
- const enum avr_builtin_id id;
+ enum insn_code icode;
+ const char *name;
+ enum avr_builtin_id id;
+ int n_args;
};
static const struct avr_builtin_description
-bdesc_1arg[] =
+avr_bdesc[] =
{
- { CODE_FOR_rotlqi3_4, "__builtin_avr_swap", AVR_BUILTIN_SWAP }
- };
-static const struct avr_builtin_description
-bdesc_2arg[] =
- {
- { CODE_FOR_fmul, "__builtin_avr_fmul", AVR_BUILTIN_FMUL },
- { CODE_FOR_fmuls, "__builtin_avr_fmuls", AVR_BUILTIN_FMULS },
- { CODE_FOR_fmulsu, "__builtin_avr_fmulsu", AVR_BUILTIN_FMULSU }
- };
+#define DEF_BUILTIN(NAME, N_ARGS, ID, TYPE, ICODE) \
+ { ICODE, NAME, ID, N_ARGS },
+#include "builtins.def"
+#undef DEF_BUILTIN
-static const struct avr_builtin_description
-bdesc_3arg[] =
- {
- { CODE_FOR_insert_bits, "__builtin_avr_insert_bits",
- AVR_BUILTIN_INSERT_BITS }
+ { CODE_FOR_nothing, NULL, 0, -1 }
};
+
/* Subroutine of avr_expand_builtin to take care of unop insns. */
static rtx
int ignore ATTRIBUTE_UNUSED)
{
size_t i;
- const struct avr_builtin_description *d;
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
const char* bname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
unsigned int id = DECL_FUNCTION_CODE (fndecl);
emit_insn (gen_nopv (GEN_INT(1)));
return 0;
- case AVR_BUILTIN_SEI:
- emit_insn (gen_enable_interrupt ());
- return 0;
-
- case AVR_BUILTIN_CLI:
- emit_insn (gen_disable_interrupt ());
- return 0;
-
- case AVR_BUILTIN_WDR:
- emit_insn (gen_wdr ());
- return 0;
-
- case AVR_BUILTIN_SLEEP:
- emit_insn (gen_sleep ());
- return 0;
-
case AVR_BUILTIN_DELAY_CYCLES:
{
arg0 = CALL_EXPR_ARG (exp, 0);
op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
- if (! CONST_INT_P (op0))
+ if (!CONST_INT_P (op0))
error ("%s expects a compile time integer constant", bname);
+ else
+ avr_expand_delay_cycles (op0);
- avr_expand_delay_cycles (op0);
return 0;
}
}
}
- for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
- if (d->id == id)
- return avr_expand_unop_builtin (d->icode, exp, target);
-
- for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
- if (d->id == id)
- return avr_expand_binop_builtin (d->icode, exp, target);
-
- for (i = 0, d = bdesc_3arg; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
- if (d->id == id)
- return avr_expand_triop_builtin (d->icode, exp, target);
-
+ for (i = 0; avr_bdesc[i].name; i++)
+ {
+ const struct avr_builtin_description *d = &avr_bdesc[i];
+
+ if (d->id == id)
+ switch (d->n_args)
+ {
+ case 0:
+ emit_insn ((GEN_FCN (d->icode)) (target));
+ return 0;
+
+ case 1:
+ return avr_expand_unop_builtin (d->icode, exp, target);
+
+ case 2:
+ return avr_expand_binop_builtin (d->icode, exp, target);
+
+ case 3:
+ return avr_expand_triop_builtin (d->icode, exp, target);
+
+ default:
+ gcc_unreachable();
+ }
+ }
+
gcc_unreachable ();
}
default:
break;
+ case AVR_BUILTIN_SWAP:
+ {
+ return fold_build2 (LROTATE_EXPR, val_type, arg[0],
+ build_int_cst (val_type, 4));
+ }
+
case AVR_BUILTIN_INSERT_BITS:
{
tree tbits = arg[1];
tree tval = arg[2];
tree tmap;
tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
- double_int map = tree_to_double_int (arg[0]);
+ double_int map;
bool changed = false;
unsigned i;
avr_map_op_t best_g;
+
+ if (TREE_CODE (arg[0]) != INTEGER_CST)
+ {
+ /* No constant as first argument: Don't fold this and run into
+ error in avr_expand_builtin. */
+
+ break;
+ }
+ map = tree_to_double_int (arg[0]);
tmap = double_int_to_tree (map_type, map);
if (TREE_CODE (tval) != INTEGER_CST
--- /dev/null
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+/* This file contains the definitions and documentation for the
+ builtins defined in the AVR part of the GNU compiler.
+ Befor including this file, define a macro
+
+ DEF_BUILTIN(NAME, N_ARGS, ID, TYPE, ICODE)
+
+ NAME: The name as visible by the user as a C string.
+ ID: An integer to identify the built-in.
+ N_ARGS: Number of input arguments. If special treatment is needed,
+ set to -1 and handle it by hand, see avr.c:avr_expand_builtin().
+ TYPE: A tree node describing the prototype of the built-in.
+ ICODE: Insn code number for the insn attached to the built-in.
+ If special treatment is needed to expand the built-in, set to -1.
+*/
+
+/* Mapped to respective instruction. */
+DEF_BUILTIN ("__builtin_avr_nop", -1, AVR_BUILTIN_NOP, void_ftype_void, -1)
+DEF_BUILTIN ("__builtin_avr_sei", 0, AVR_BUILTIN_SEI, void_ftype_void, CODE_FOR_enable_interrupt)
+DEF_BUILTIN ("__builtin_avr_cli", 0, AVR_BUILTIN_CLI, void_ftype_void, CODE_FOR_disable_interrupt)
+DEF_BUILTIN ("__builtin_avr_wdr", 0, AVR_BUILTIN_WDR, void_ftype_void, CODE_FOR_wdr)
+DEF_BUILTIN ("__builtin_avr_sleep", 0, AVR_BUILTIN_SLEEP, void_ftype_void, CODE_FOR_sleep)
+
+/* Mapped to respective instruction but might alse be folded away
+ or emit as libgcc call if ISA does not provide the instruction. */
+DEF_BUILTIN ("__builtin_avr_swap", 1, AVR_BUILTIN_SWAP, uchar_ftype_uchar, CODE_FOR_rotlqi3_4)
+DEF_BUILTIN ("__builtin_avr_fmul", 2, AVR_BUILTIN_FMUL, uint_ftype_uchar_uchar, CODE_FOR_fmul)
+DEF_BUILTIN ("__builtin_avr_fmuls", 2, AVR_BUILTIN_FMULS, int_ftype_char_char, CODE_FOR_fmuls)
+DEF_BUILTIN ("__builtin_avr_fmulsu", 2, AVR_BUILTIN_FMULSU, int_ftype_char_uchar, CODE_FOR_fmulsu)
+
+/* More complex stuff that cannot be mapped 1:1 to an instruction. */
+DEF_BUILTIN ("__builtin_avr_delay_cycles", -1, AVR_BUILTIN_DELAY_CYCLES, void_ftype_ulong, -1)
+DEF_BUILTIN ("__builtin_avr_insert_bits", 3, AVR_BUILTIN_INSERT_BITS, uchar_ftype_ulong_uchar_uchar, CODE_FOR_insert_bits)