[PATCH, GCC/ARM, 9/10] Call nscall function with blxns
[official-gcc.git] / gcc / testsuite / gcc.target / arm / cmse / cmse-1.c
blobddfcfacab5f601a729319a9d2dab03e61ee56bca
1 /* { dg-do compile } */
2 /* { dg-options "-Os -mcmse -fdump-rtl-expand" } */
4 #include <arm_cmse.h>
6 extern int a;
7 extern int bar (void);
9 int foo (char * p)
11 cmse_address_info_t cait;
13 cait = cmse_TT (&a);
14 if (cait.flags.mpu_region)
15 a++;
17 cait = cmse_TT_fptr (&bar);
18 if (cait.flags.mpu_region)
19 a+= bar ();
21 cait = cmse_TTA (&a);
22 if (cait.flags.mpu_region)
23 a++;
25 cait = cmse_TTA_fptr (&bar);
26 if (cait.flags.mpu_region)
27 a+= bar ();
29 cait = cmse_TTT (&a);
30 if (cait.flags.mpu_region)
31 a++;
33 cait = cmse_TTT_fptr (&bar);
34 if (cait.flags.mpu_region)
35 a+= bar ();
37 cait = cmse_TTAT (&a);
38 if (cait.flags.mpu_region)
39 a++;
41 cait = cmse_TTAT_fptr (&bar);
42 if (cait.flags.mpu_region)
43 a+= bar ();
45 p = (char *) cmse_check_address_range ((void *) p, sizeof (char), 0);
46 p = (char *) cmse_check_address_range ((void *) p, sizeof (char),
47 CMSE_MPU_UNPRIV);
48 p = (char *) cmse_check_address_range ((void *) p, sizeof (char),
49 CMSE_MPU_READWRITE);
50 p = (char *) cmse_check_address_range ((void *) p, sizeof (char),
51 CMSE_MPU_UNPRIV | CMSE_MPU_READ);
52 p = (char *) cmse_check_address_range ((void *) p, sizeof (char),
53 CMSE_AU_NONSECURE
54 | CMSE_MPU_NONSECURE);
55 p = (char *) cmse_check_address_range ((void *) p, sizeof (char),
56 CMSE_NONSECURE | CMSE_MPU_UNPRIV);
58 p = (char *) cmse_check_pointed_object (p, CMSE_NONSECURE | CMSE_MPU_UNPRIV);
60 return a;
62 /* { dg-final { scan-assembler-times "\ttt " 2 } } */
63 /* { dg-final { scan-assembler-times "ttt " 2 } } */
64 /* { dg-final { scan-assembler-times "tta " 2 } } */
65 /* { dg-final { scan-assembler-times "ttat " 2 } } */
66 /* { dg-final { scan-assembler-times "bl.cmse_check_address_range" 7 } } */
67 /* { dg-final { scan-assembler-not "cmse_check_pointed_object" } } */
69 int __attribute__ ((cmse_nonsecure_entry))
70 baz (void)
72 return cmse_nonsecure_caller ();
74 /* { dg-final { scan-assembler "baz:" } } */
75 /* { dg-final { scan-assembler "__acle_se_baz:" } } */
76 /* { dg-final { scan-assembler-not "\tcmse_nonsecure_caller" } } */
77 /* Look for an andsi of 1 with a register in function baz, ie.
79 ;; Function baz<anything>
80 <any line without '('>
81 (insn <anything but '('> (set (reg<any register modifier>:SI <anything but ')'>)
82 (and:SI (reg<any register modifier>:SI <anything but ')'>)
83 (const_int 1 <anything but ')'>)<anything but '('>
84 <optional: (nil)<anything but '('>>
85 (insn
87 /* { dg-final { scan-rtl-dump "\n;; Function baz\[^\n\]*\[^(\]+\[^;\]*\n\\(insn \[^(\]+ \\(set \\(reg\[^:\]*:SI \[^)\]+\\)\[^(\]*\\(and:SI \\(reg\[^:\]*:SI \[^)\]+\\)\[^(\]*\\((const_int 1|reg\[^:\]*:SI) \[^)\]+\\)\[^(\]+(\\(nil\\)\[^(\]+)?\\(insn" expand } } */
89 typedef int __attribute__ ((cmse_nonsecure_call)) (int_nsfunc_t) (void);
91 int default_callback (void)
93 return 0;
96 int_nsfunc_t * fp = (int_nsfunc_t *) default_callback;
98 void __attribute__ ((cmse_nonsecure_entry))
99 qux (int_nsfunc_t * callback)
101 fp = cmse_nsfptr_create (callback);
103 /* { dg-final { scan-assembler "qux:" } } */
104 /* { dg-final { scan-assembler "__acle_se_qux:" } } */
105 /* { dg-final { scan-assembler "bic" } } */
106 /* { dg-final { scan-assembler "push\t\{r4, r5, r6" } } */
107 /* { dg-final { scan-assembler "vstr\tFPCXTNS, \\\[sp, #-4\\\]!" { target arm_cmse_clear_ok } } } */
108 /* { dg-final { scan-assembler "vscclrm\t\{s0-s15, VPR\}" { target arm_cmse_clear_ok } } } */
109 /* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" { target arm_cmse_clear_ok } } } */
110 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" { target arm_cmse_clear_ok } } } */
111 /* { dg-final { scan-assembler "msr\tAPSR_nzcvq" { target { ! arm_cmse_clear_ok } } } } */
112 /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, r10, fp\}" { target arm_cmse_clear_ok } } } */
113 /* Check the right registers are cleared and none appears twice. */
114 /* { dg-final { scan-assembler "clrm\t\{(r0, )?(r1, )?(r2, )?(r3, )?(r4, )?(r5, )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, )?APSR\}" { target arm_cmse_clear_ok } } } */
115 /* Check that the right number of registers is cleared and thus only one
116 register is missing. */
117 /* { dg-final { scan-assembler "clrm\t\{((r\[0-9\]|r10|fp|ip), ){12}APSR\}" { target arm_cmse_clear_ok } } } */
118 /* Check that no cleared register is used for blxns. */
119 /* { dg-final { scan-assembler-not "clrm\t\{\[^\}\]\+(r\[0-9\]|r10|fp|ip),\[^\}\]\+\}(?!.*clrm.*blxns).*blxns\t\\1" { target arm_cmse_clear_ok } } } */
120 /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, fp\}" { target arm_cmse_clear_ok } } } */
122 int call_callback (void)
124 if (cmse_is_nsfptr (fp))
125 return fp ();
126 else
127 return default_callback ();
129 /* { dg-final { scan-assembler-times "bl\\s+__gnu_cmse_nonsecure_call" 1 { target { ! arm_cmse_clear_ok } } } } */
130 /* { dg-final { scan-assembler "blxns" { target arm_cmse_clear_ok } } } */