[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[avr-gcc-list] Add builtins in avr target.
From: |
Anatoly Sokolov |
Subject: |
[avr-gcc-list] Add builtins in avr target. |
Date: |
Sat, 5 Apr 2008 00:51:12 +0400 |
Hello.
This patch add '__builtin_avr_swap', '__builtin_avr_sei' and
'__builtin_avr_cli' builtins in avr backend. It will allow to use 'SWAP',
'SEI' and 'CLI' instructions, without use inline assembly.
I wish to add:
1. builtins for 'SLEEP' and 'WDR' instructions;
2. builtins for 'FMUL*' instructions;
3. builtin similarly to IAR '__delay_cycles';
4. builtin for 'DES' xmega instruction.
Your suggestions?
main.c:
void __builtin_avr_sei(void);
void __builtin_avr_cli(void);
unsigned char __builtin_avr_swap(unsigned char);
extern unsigned char a;
unsigned char a;
int
main (void)
{
a = __builtin_avr_swap(a);
__builtin_avr_sei();
__builtin_avr_cli();
return 0;
}
main.lst:
a = __builtin_avr_swap(a);
ce: 80 91 00 01 lds r24, 0x0100
d2: 82 95 swap r24
d4: 80 93 00 01 sts 0x0100, r24
__builtin_avr_sei();
d8: 78 94 sei
__builtin_avr_cli();
da: f8 94 cli
Index: gcc/config/avr/avr.md
===================================================================
--- gcc/config/avr/avr.md (revision 133907)
+++ gcc/config/avr/avr.md (working copy)
@@ -52,11 +52,12 @@
(UNSPEC_STRLEN 0)
(UNSPEC_INDEX_JMP 1)
- (UNSPEC_SEI 2)
- (UNSPEC_CLI 3)
+ (UNSPEC_SWAP 2)
(UNSPECV_PROLOGUE_SAVES 0)
- (UNSPECV_EPILOGUE_RESTORES 1)])
+ (UNSPECV_EPILOGUE_RESTORES 1)
+ (UNSPECV_SEI 2)
+ (UNSPECV_CLI 3)])
(include "predicates.md")
(include "constraints.md")
@@ -1322,6 +1323,18 @@
[(set_attr "length" "4")
(set_attr "cc" "set_n")])
+;;swap_swap_swap_swap_swap_swap_swap_swap_swap_swap_swap_swap_swap_swap_swap
+;; swap
+
+(define_insn "swap"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (unspec:QI [(match_operand:QI 1 "register_operand" "0")]
+ UNSPEC_SWAP))]
+ ""
+ "swap %0"
+ [(set_attr "length" "1")
+ (set_attr "cc" "none")])
+
;;<< << << << << << << << << << << << << << << << << << << << << << << << << <<
;; arithmetic shift left
@@ -2751,7 +2764,7 @@
;; Enable Interrupts
(define_insn "enable_interrupt"
- [(unspec [(const_int 0)] UNSPEC_SEI)]
+ [(unspec_volatile [(const_int 0)] UNSPECV_SEI)]
""
"sei"
[(set_attr "length" "1")
@@ -2760,7 +2773,7 @@
;; Disable Interrupts
(define_insn "disable_interrupt"
- [(unspec [(const_int 0)] UNSPEC_CLI)]
+ [(unspec_volatile [(const_int 0)] UNSPECV_CLI)]
""
"cli"
[(set_attr "length" "1")
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c (revision 133907)
+++ gcc/config/avr/avr.c (working copy)
@@ -30,6 +30,7 @@
#include "insn-config.h"
#include "conditions.h"
#include "insn-attr.h"
+#include "insn-codes.h"
#include "flags.h"
#include "reload.h"
#include "tree.h"
@@ -39,7 +40,9 @@
#include "obstack.h"
#include "function.h"
#include "recog.h"
+#include "optabs.h"
#include "ggc.h"
+#include "langhooks.h"
#include "tm_p.h"
#include "target.h"
#include "target-def.h"
@@ -81,6 +85,9 @@
static int avr_address_cost (rtx);
static bool avr_return_in_memory (const_tree, const_tree);
static struct machine_function * avr_init_machine_status (void);
+static void avr_init_builtins (void);
+static rtx avr_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+
/* Allocate registers from r25 to r8 for parameters for function calls. */
#define FIRST_CUM_REG 26
@@ -334,6 +341,12 @@
#undef TARGET_STRICT_ARGUMENT_NAMING
#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS avr_init_builtins
+
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN avr_expand_builtin
+
struct gcc_target targetm = TARGET_INITIALIZER;
void
@@ -5947,4 +5983,118 @@
return false;
}
+/* Codes for all the AVR builtins. */
+
+enum avr_builtins
+{
+ AVR_BUILTIN_SEI,
+ AVR_BUILTIN_CLI,
+ AVR_BUILTIN_SWAP
+};
+
+#define def_builtin(NAME, TYPE, CODE) \
+do { \
+ add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
+ NULL, NULL_TREE); \
+} while (0)
+
+/* Set up all builtin functions for this target. */
+
+static void
+avr_init_builtins (void)
+{
+ tree void_ftype_void
+ = build_function_type (void_type_node, void_list_node);
+ tree uchar_ftype_uchar
+ = build_function_type_list (unsigned_char_type_node,
+ unsigned_char_type_node,
+ NULL_TREE);
+
+ 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_swap", uchar_ftype_uchar, AVR_BUILTIN_SWAP);
+}
+
+struct builtin_description
+{
+ const enum insn_code icode;
+ const char *const name;
+ const enum avr_builtins code;
+};
+
+static const struct builtin_description bdesc_1arg[] =
+{
+ { CODE_FOR_swap, "__builtin_avr_swap", AVR_BUILTIN_SWAP }
+};
+
+/* Subroutine of bfin_expand_builtin to take care of unop insns. */
+
+static rtx
+avr_expand_unop_builtin (enum insn_code icode, tree exp,
+ rtx target)
+{
+ rtx pat;
+ tree arg0 = CALL_EXPR_ARG (exp, 0);
+ rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ enum machine_mode op0mode = GET_MODE (op0);
+ enum machine_mode tmode = insn_data[icode].operand[0].mode;
+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
+
+ if (! target
+ || GET_MODE (target) != tmode
+ || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+ target = gen_reg_rtx (tmode);
+
+ if (op0mode == SImode && mode0 == HImode)
+ {
+ op0mode = HImode;
+ op0 = gen_lowpart (HImode, op0);
+ }
+ gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
+
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ pat = GEN_FCN (icode) (target, op0);
+ if (! pat)
+ return 0;
+ emit_insn (pat);
+ return target;
+}
+
+/* Expand an expression EXP that calls a built-in function,
+ with result going to TARGET if that's convenient
+ (and in mode MODE if that's convenient).
+ SUBTARGET may be used as the target for computing one of EXP's operands.
+ IGNORE is nonzero if the value is to be ignored. */
+
+static rtx
+avr_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
+ rtx subtarget ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
+{
+ size_t i;
+ const struct builtin_description *d;
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+
+ switch (fcode)
+ {
+ case AVR_BUILTIN_SEI:
+ emit_insn (gen_enable_interrupt ());
+ return 0;
+ case AVR_BUILTIN_CLI:
+ emit_insn (gen_disable_interrupt ());
+ return 0;
+ }
+
+ for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
+ if (d->code == fcode)
+ return avr_expand_unop_builtin (d->icode, exp, target);
+
+ gcc_unreachable ();
+}
+
#include "gt-avr.h"
Anatoly.