avr-gcc-list
[Top][All Lists]
Advanced

[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.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]