This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Implementation of swi attribute for ARM


Hello!
I'm new to GCC internals, but I'm using GCC for couple of years.
Yesterday I found that GCC does not support calling SWI routines from C/C++
code.
For example, in other ARM-targeted compiliers developer can use such syntax
for function prototype:
In ARM IAR:
#pragma swi_number=0x15
int some_call(int, int);
In RVDS:
__swi(0x15) int some_call(int, int);
And then just call function as usual:
a = some_call(5, 8);
GCC lacks this feauture, so I've decided to go on Free Software way - if your
need something, implement it yourself =)
I can't write any testsuite, because I don't know how to do it, sorry. I
tested some programs written for IAR, they compiled and launched successfully.
I've also tested some programs with functions that don't use this attribute -
they was unaffected by this patch. So I decided to send it to this mailing
list.
Changelog and patch included in attachment.
I tested cross-compiling, host=i686-pc-linux-gnu and host=x86_64-pc-linux-gnu,
target=arm-linux-gnueabi. Works stable and fine.

Barracuda
diff -aur sources/gcc-4.5.1/gcc/config/arm//arm.c gcc-4.5.1/gcc/config/arm//arm.c
--- sources/gcc-4.5.1/gcc/config/arm//arm.c	2010-07-12 20:05:41.000000000 +0600
+++ gcc-4.5.1/gcc/config/arm//arm.c	2012-02-21 04:24:13.295235261 +0600
@@ -225,6 +225,7 @@
 static void arm_trampoline_init (rtx, tree, rtx);
 static rtx arm_trampoline_adjust_address (rtx);
 
+static tree arm_handle_swi_attribute (tree *, tree, tree, int, bool *);
 
 /* Table of machine attributes.  */
 static const struct attribute_spec arm_attribute_table[] =
@@ -243,6 +246,7 @@
   { "isr",          0, 1, false, false, false, arm_handle_isr_attribute },
   { "interrupt",    0, 1, false, false, false, arm_handle_isr_attribute },
   { "naked",        0, 0, true,  false, false, arm_handle_fndecl_attribute },
+  { "swi",          1, 1, false, false, false, arm_handle_swi_attribute },
 #ifdef ARM_PE
   /* ARM/PE has three new attributes:
      interfacearm - ?
@@ -4595,6 +4601,47 @@
   return NULL_TREE;
 }
 
+static tree
+arm_handle_swi_attribute (tree *node, tree name, tree args, int flags,
+			  bool *no_add_attrs)
+{
+  if (DECL_P (*node))
+    {
+      if (TREE_CODE (*node) != FUNCTION_DECL)
+	{
+	  warning (OPT_Wattributes, "%qE attribute only applies to functions",
+		   name);
+	  *no_add_attrs = true;
+	} else {
+          tree cst = TREE_VALUE (args);
+          if (TREE_CODE (cst) != INTEGER_CST)
+            {
+              error ("%qE attribute requires an integer constant argument",
+                     name);
+              *no_add_attrs = true;
+            }
+          else if (TARGET_ARM && (compare_tree_int (cst, 0xFFFFFF) > 0))
+            {
+              error ("argument to %qE attribute larger than 0xFFFFFF",
+                     name);
+              *no_add_attrs = true;
+            }
+          else if (TARGET_THUMB && (compare_tree_int (cst, 0xFF) > 0))
+            {
+              error ("argument to %qE attribute larger than 0xFF",
+                     name);
+              *no_add_attrs = true;
+            }
+        }
+    } else {
+      warning (OPT_Wattributes,
+               "%qE attribute can be applied only to function prototype");
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "pcs" attribute; arguments as in struct
    attribute_spec.handler.  */
 static tree
@@ -4768,6 +4821,52 @@
   return TARGET_LONG_CALLS;
 }
 
+bool
+arm_is_swicall (tree decl)
+{
+  tree attrs;
+  tree a;
+
+  if (!decl)
+  {
+    return false;
+  }
+
+  attrs = DECL_ATTRIBUTES ( decl);
+  a = lookup_attribute ("swi", attrs);
+  if (a == NULL_TREE)
+  {
+    return false;
+  }
+
+  return true;
+}
+
+const char *
+output_swicall (tree decl)
+{
+  tree attrs;
+  tree a;
+  tree cst;
+  int value;
+  char *buf = ggc_alloc_cleared (32);
+
+  attrs = DECL_ATTRIBUTES (decl);
+  a = lookup_attribute ("swi", attrs);
+  if (TREE_VALUE (a) == NULL_TREE)
+    return "ERROR";
+
+  cst = TREE_VALUE (TREE_VALUE (a));
+  if (TREE_CODE (cst) != INTEGER_CST)
+    return "ERROR1";
+
+  value = TREE_INT_CST_LOW (cst);
+
+  snprintf (buf, 32, "swi%%?\t%d", value);
+
+  return buf;
+}
+
 /* Return nonzero if it is ok to make a tail-call to DECL.  */
 static bool
 arm_function_ok_for_sibcall (tree decl, tree exp)
diff -aur sources/gcc-4.5.1/gcc/config/arm//arm.md gcc-4.5.1/gcc/config/arm//arm.md
--- sources/gcc-4.5.1/gcc/config/arm//arm.md	2010-07-31 04:35:40.000000000 +0600
+++ gcc-4.5.1/gcc/config/arm//arm.md	2012-02-21 04:20:46.846224042 +0600
@@ -8646,7 +8646,11 @@
    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
   "*
   {
-    return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
+    bool is_swi = arm_is_swicall (SYMBOL_REF_DECL (operands[1]));
+    if (is_swi)
+      return output_swicall (SYMBOL_REF_DECL (operands[1]));
+    else
+      return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
   }"
   [(set_attr "type" "call")]
 )
@@ -8673,7 +8678,14 @@
   "TARGET_THUMB
    && GET_CODE (operands[1]) == SYMBOL_REF
    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
-  "bl\\t%a1"
+  "*
+  {
+    bool is_swi = arm_is_swicall (SYMBOL_REF_DECL (operands[1]));
+    if (is_swi)
+      return output_swicall (SYMBOL_REF_DECL (operands[1]));
+    else
+      return \"bl\\t%a1\";
+  }"
   [(set_attr "length" "4")
    (set_attr "type" "call")]
 )
diff -aur sources/gcc-4.5.1/gcc/config/arm//arm-protos.h gcc-4.5.1/gcc/config/arm//arm-protos.h
--- sources/gcc-4.5.1/gcc/config/arm//arm-protos.h	2010-07-05 18:45:19.000000000 +0600
+++ gcc-4.5.1/gcc/config/arm//arm-protos.h	2012-02-21 04:04:38.185415081 +0600
@@ -120,6 +120,7 @@
 extern void arm_emit_call_insn (rtx, rtx);
 extern const char *output_call (rtx *);
 extern const char *output_call_mem (rtx *);
+extern const char *output_swicall (tree decl);
 void arm_emit_movpair (rtx, rtx);
 extern const char *output_mov_long_double_fpa_from_arm (rtx *);
 extern const char *output_mov_long_double_arm_from_fpa (rtx *);
@@ -141,6 +144,7 @@
 extern void arm_final_prescan_insn (rtx);
 extern int arm_debugger_arg_offset (int, rtx);
 extern bool arm_is_long_call_p (tree);
+extern bool arm_is_swicall (tree);
 extern int    arm_emit_vector_const (FILE *, rtx);
 extern void arm_emit_fp16_const (rtx c);
 extern const char * arm_output_load_gr (rtx *);

Attachment: Chlog.txt
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]