1 /*
2  * Copyright (c) 2013 Google Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 #include <compiler.h>
24 #include <kernel/debug.h>
25 
26 __ALIGNED(8) __NAKED
27 #if     (__CORTEX_M >= 0x03) || (CORTEX_SC >= 300)
28 
spin_cycles(uint32_t cycles)29 void spin_cycles(uint32_t cycles)
30 {
31     asm (
32         /* 4 cycles per loop, subtract out 8 cycles for the overhead of the next
33          * 4 instructions, plus the call into and return from the function.
34          * Then, add 3 then >> 2 to round up to the number of loop iterations.
35          */
36         "subs r1, %[cycles], #5\n"
37         "asrs r1, r1, #2\n"
38         "ble .Ldone\n"
39 
40         /* Padding to stay aligned on an 8 byte boundary, also has the added
41          * advantage of normalizing the overhead (1+1+2 cycles if the branch is
42          * take, or 1+1+1+1 cycles if the branch is skipped and the nop is
43          * executed)
44          */
45         "nop\n"
46 
47         /* Main delay loop.
48          * sub is 1 cycle
49          * nop is 1 cycle
50          * branch is 2 cycles
51          */
52         ".Lloop:\n"
53         "subs r1, r1, #1\n"
54         "nop\n"
55         "bne .Lloop\n"
56 
57         ".Ldone:\n"
58         "bx lr\n"
59         :                       /* no output */
60         : [cycles] "r" (cycles) /* input is cycles */
61         : "r1"                  /* r1 gets clobbered */
62     );
63 }
64 
65 #else
66 /* Cortex-M0 & Cortex-M0+    */
67 void spin_cycles(uint32_t cycles)
68 {
69     asm (
70         /* 4 cycles per loop, subtract out 8 cycles for the overhead of the next
71          * 4 instructions, plus the call into and return from the function.
72          * Then, add 3 then >> 2 to round up to the number of loop iterations.
73          */
74         "sub r1, %[cycles], #5\n"
75         "asr r1, r1, #2\n"
76         "cmp r1, #0\n"
77         "ble .Ldone\n"
78 
79         /* Padding to stay aligned on an 8 byte boundary, also has the added
80          * advantage of normalizing the overhead (1+1+2 cycles if the branch is
81          * take, or 1+1+1+1 cycles if the branch is skipped and the nop is
82          * executed)
83          */
84         "nop\n"
85 
86         /* Main delay loop.
87          * sub is 1 cycle
88          * nop is 1 cycle
89          * branch is 2 cycles
90          */
91         ".Lloop:\n"
92         "sub r1, r1, #1\n"
93         "cmp r1,#0\n"
94         "bne .Lloop\n"
95 
96         ".Ldone:\n"
97         "bx lr\n"
98         :                       /* no output */
99         : [cycles] "r" (cycles) /* input is cycles */
100         : "r1"                  /* r1 gets clobbered */
101     );
102 }
103 #endif
104