1*10465441SEvalZero /*
2*10465441SEvalZero * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
3*10465441SEvalZero *
4*10465441SEvalZero * Licensed under the Apache License, Version 2.0 (the "License");
5*10465441SEvalZero * you may not use this file except in compliance with the License.
6*10465441SEvalZero * You may obtain a copy of the License at
7*10465441SEvalZero *
8*10465441SEvalZero * http://www.apache.org/licenses/LICENSE-2.0
9*10465441SEvalZero *
10*10465441SEvalZero * Unless required by applicable law or agreed to in writing, software
11*10465441SEvalZero * distributed under the License is distributed on an "AS IS" BASIS,
12*10465441SEvalZero * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*10465441SEvalZero * See the License for the specific language governing permissions and
14*10465441SEvalZero * limitations under the License.
15*10465441SEvalZero */
16*10465441SEvalZero
17*10465441SEvalZero /******************************************************************************
18*10465441SEvalZero * @file csi_instr.h
19*10465441SEvalZero * @brief CSI Header File for instruct.
20*10465441SEvalZero * @version V1.0
21*10465441SEvalZero * @date 02. June 2017
22*10465441SEvalZero ******************************************************************************/
23*10465441SEvalZero
24*10465441SEvalZero #ifndef _CSI_INSTR_H_
25*10465441SEvalZero #define _CSI_INSTR_H_
26*10465441SEvalZero
27*10465441SEvalZero
28*10465441SEvalZero #define __CSI_GCC_OUT_REG(r) "=r" (r)
29*10465441SEvalZero #define __CSI_GCC_USE_REG(r) "r" (r)
30*10465441SEvalZero
31*10465441SEvalZero /**
32*10465441SEvalZero \brief No Operation
33*10465441SEvalZero \details No Operation does nothing. This instruction can be used for code alignment purposes.
34*10465441SEvalZero */
__NOP(void)35*10465441SEvalZero __ALWAYS_INLINE void __NOP(void)
36*10465441SEvalZero {
37*10465441SEvalZero __ASM volatile("nop");
38*10465441SEvalZero }
39*10465441SEvalZero
40*10465441SEvalZero
41*10465441SEvalZero /**
42*10465441SEvalZero \brief Wait For Interrupt
43*10465441SEvalZero \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
44*10465441SEvalZero */
__WFI(void)45*10465441SEvalZero __ALWAYS_INLINE void __WFI(void)
46*10465441SEvalZero {
47*10465441SEvalZero __ASM volatile("wait");
48*10465441SEvalZero }
49*10465441SEvalZero
50*10465441SEvalZero /**
51*10465441SEvalZero \brief Wait For Interrupt
52*10465441SEvalZero \details Wait For Interrupt is a hint instruction that suspends execution until one interrupt occurs.
53*10465441SEvalZero */
__WAIT(void)54*10465441SEvalZero __ALWAYS_INLINE void __WAIT(void)
55*10465441SEvalZero {
56*10465441SEvalZero __ASM volatile("wait");
57*10465441SEvalZero }
58*10465441SEvalZero
59*10465441SEvalZero /**
60*10465441SEvalZero \brief Doze For Interrupt
61*10465441SEvalZero \details Doze For Interrupt is a hint instruction that suspends execution until one interrupt occurs.
62*10465441SEvalZero */
__DOZE(void)63*10465441SEvalZero __ALWAYS_INLINE void __DOZE(void)
64*10465441SEvalZero {
65*10465441SEvalZero __ASM volatile("doze");
66*10465441SEvalZero }
67*10465441SEvalZero
68*10465441SEvalZero /**
69*10465441SEvalZero \brief Stop For Interrupt
70*10465441SEvalZero \details Stop For Interrupt is a hint instruction that suspends execution until one interrupt occurs.
71*10465441SEvalZero */
__STOP(void)72*10465441SEvalZero __ALWAYS_INLINE void __STOP(void)
73*10465441SEvalZero {
74*10465441SEvalZero __ASM volatile("stop");
75*10465441SEvalZero }
76*10465441SEvalZero
77*10465441SEvalZero /**
78*10465441SEvalZero \brief Instruction Synchronization Barrier
79*10465441SEvalZero \details Instruction Synchronization Barrier flushes the pipeline in the processor,
80*10465441SEvalZero so that all instructions following the ISB are fetched from cache or memory,
81*10465441SEvalZero after the instruction has been completed.
82*10465441SEvalZero */
__ISB(void)83*10465441SEvalZero __ALWAYS_INLINE void __ISB(void)
84*10465441SEvalZero {
85*10465441SEvalZero __ASM volatile("sync"::: "memory");
86*10465441SEvalZero }
87*10465441SEvalZero
88*10465441SEvalZero
89*10465441SEvalZero /**
90*10465441SEvalZero \brief Data Synchronization Barrier
91*10465441SEvalZero \details Acts as a special kind of Data Memory Barrier.
92*10465441SEvalZero It completes when all explicit memory accesses before this instruction complete.
93*10465441SEvalZero */
__DSB(void)94*10465441SEvalZero __ALWAYS_INLINE void __DSB(void)
95*10465441SEvalZero {
96*10465441SEvalZero __ASM volatile("sync"::: "memory");
97*10465441SEvalZero }
98*10465441SEvalZero
99*10465441SEvalZero
100*10465441SEvalZero /**
101*10465441SEvalZero \brief Data Memory Barrier
102*10465441SEvalZero \details Ensures the apparent order of the explicit memory operations before
103*10465441SEvalZero and after the instruction, without ensuring their completion.
104*10465441SEvalZero */
__DMB(void)105*10465441SEvalZero __ALWAYS_INLINE void __DMB(void)
106*10465441SEvalZero {
107*10465441SEvalZero __ASM volatile("sync"::: "memory");
108*10465441SEvalZero }
109*10465441SEvalZero
110*10465441SEvalZero
111*10465441SEvalZero /**
112*10465441SEvalZero \brief Reverse byte order (32 bit)
113*10465441SEvalZero \details Reverses the byte order in integer value.
114*10465441SEvalZero \param [in] value Value to reverse
115*10465441SEvalZero \return Reversed value
116*10465441SEvalZero */
__REV(uint32_t value)117*10465441SEvalZero __ALWAYS_INLINE uint32_t __REV(uint32_t value)
118*10465441SEvalZero {
119*10465441SEvalZero return __builtin_bswap32(value);
120*10465441SEvalZero }
121*10465441SEvalZero
122*10465441SEvalZero
123*10465441SEvalZero /**
124*10465441SEvalZero \brief Reverse byte order (16 bit)
125*10465441SEvalZero \details Reverses the byte order in two unsigned short values.
126*10465441SEvalZero \param [in] value Value to reverse
127*10465441SEvalZero \return Reversed value
128*10465441SEvalZero */
__REV16(uint32_t value)129*10465441SEvalZero __ALWAYS_INLINE uint32_t __REV16(uint32_t value)
130*10465441SEvalZero {
131*10465441SEvalZero uint32_t result;
132*10465441SEvalZero #if (__CK80X >= 2)
133*10465441SEvalZero __ASM volatile("revh %0, %1" : __CSI_GCC_OUT_REG(result) : __CSI_GCC_USE_REG(value));
134*10465441SEvalZero #else
135*10465441SEvalZero result = ((value & 0xFF000000) >> 8) | ((value & 0x00FF0000) << 8) |
136*10465441SEvalZero ((value & 0x0000FF00) >> 8) | ((value & 0x000000FF) << 8);
137*10465441SEvalZero #endif
138*10465441SEvalZero return (result);
139*10465441SEvalZero }
140*10465441SEvalZero
141*10465441SEvalZero
142*10465441SEvalZero /**
143*10465441SEvalZero \brief Reverse byte order in signed short value
144*10465441SEvalZero \details Reverses the byte order in a signed short value with sign extension to integer.
145*10465441SEvalZero \param [in] value Value to reverse
146*10465441SEvalZero \return Reversed value
147*10465441SEvalZero */
__REVSH(int32_t value)148*10465441SEvalZero __ALWAYS_INLINE int32_t __REVSH(int32_t value)
149*10465441SEvalZero {
150*10465441SEvalZero return (short)(((value & 0xFF00) >> 8) | ((value & 0x00FF) << 8));
151*10465441SEvalZero }
152*10465441SEvalZero
153*10465441SEvalZero
154*10465441SEvalZero /**
155*10465441SEvalZero \brief Rotate Right in unsigned value (32 bit)
156*10465441SEvalZero \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
157*10465441SEvalZero \param [in] op1 Value to rotate
158*10465441SEvalZero \param [in] op2 Number of Bits to rotate
159*10465441SEvalZero \return Rotated value
160*10465441SEvalZero */
__ROR(uint32_t op1,uint32_t op2)161*10465441SEvalZero __ALWAYS_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
162*10465441SEvalZero {
163*10465441SEvalZero return (op1 >> op2) | (op1 << (32U - op2));
164*10465441SEvalZero }
165*10465441SEvalZero
166*10465441SEvalZero
167*10465441SEvalZero /**
168*10465441SEvalZero \brief Breakpoint
169*10465441SEvalZero \details Causes the processor to enter Debug state
170*10465441SEvalZero Debug tools can use this to investigate system state when the instruction at a particular address is reached.
171*10465441SEvalZero */
__BKPT()172*10465441SEvalZero __ALWAYS_INLINE void __BKPT()
173*10465441SEvalZero {
174*10465441SEvalZero __ASM volatile("bkpt");
175*10465441SEvalZero }
176*10465441SEvalZero
177*10465441SEvalZero /**
178*10465441SEvalZero \brief Reverse bit order of value
179*10465441SEvalZero \details Reverses the bit order of the given value.
180*10465441SEvalZero \param [in] value Value to reverse
181*10465441SEvalZero \return Reversed value
182*10465441SEvalZero */
__RBIT(uint32_t value)183*10465441SEvalZero __ALWAYS_INLINE uint32_t __RBIT(uint32_t value)
184*10465441SEvalZero {
185*10465441SEvalZero uint32_t result;
186*10465441SEvalZero
187*10465441SEvalZero #if (__CK80X >= 0x03U)
188*10465441SEvalZero __ASM volatile("brev %0, %1" : "=r"(result) : "r"(value));
189*10465441SEvalZero #else
190*10465441SEvalZero int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */
191*10465441SEvalZero
192*10465441SEvalZero result = value; /* r will be reversed bits of v; first get LSB of v */
193*10465441SEvalZero
194*10465441SEvalZero for (value >>= 1U; value; value >>= 1U)
195*10465441SEvalZero {
196*10465441SEvalZero result <<= 1U;
197*10465441SEvalZero result |= value & 1U;
198*10465441SEvalZero s--;
199*10465441SEvalZero }
200*10465441SEvalZero
201*10465441SEvalZero result <<= s; /* shift when v's highest bits are zero */
202*10465441SEvalZero #endif
203*10465441SEvalZero return (result);
204*10465441SEvalZero }
205*10465441SEvalZero
206*10465441SEvalZero
207*10465441SEvalZero /**
208*10465441SEvalZero \brief Count leading zeros
209*10465441SEvalZero \details Counts the number of leading zeros of a data value.
210*10465441SEvalZero \param [in] value Value to count the leading zeros
211*10465441SEvalZero \return number of leading zeros in value
212*10465441SEvalZero */
213*10465441SEvalZero #define __CLZ __builtin_clz
214*10465441SEvalZero /**
215*10465441SEvalZero \details This function saturates a signed value.
216*10465441SEvalZero \param [in] x Value to be saturated
217*10465441SEvalZero \param [in] y Bit position to saturate to [1..32]
218*10465441SEvalZero \return Saturated value.
219*10465441SEvalZero */
__SSAT(int32_t x,uint32_t y)220*10465441SEvalZero __ALWAYS_INLINE int32_t __SSAT(int32_t x, uint32_t y)
221*10465441SEvalZero {
222*10465441SEvalZero int32_t posMax, negMin;
223*10465441SEvalZero uint32_t i;
224*10465441SEvalZero
225*10465441SEvalZero posMax = 1;
226*10465441SEvalZero
227*10465441SEvalZero for (i = 0; i < (y - 1); i++)
228*10465441SEvalZero {
229*10465441SEvalZero posMax = posMax * 2;
230*10465441SEvalZero }
231*10465441SEvalZero
232*10465441SEvalZero if (x > 0)
233*10465441SEvalZero {
234*10465441SEvalZero posMax = (posMax - 1);
235*10465441SEvalZero
236*10465441SEvalZero if (x > posMax)
237*10465441SEvalZero {
238*10465441SEvalZero x = posMax;
239*10465441SEvalZero }
240*10465441SEvalZero
241*10465441SEvalZero // x &= (posMax * 2 + 1);
242*10465441SEvalZero }
243*10465441SEvalZero else
244*10465441SEvalZero {
245*10465441SEvalZero negMin = -posMax;
246*10465441SEvalZero
247*10465441SEvalZero if (x < negMin)
248*10465441SEvalZero {
249*10465441SEvalZero x = negMin;
250*10465441SEvalZero }
251*10465441SEvalZero
252*10465441SEvalZero // x &= (posMax * 2 - 1);
253*10465441SEvalZero }
254*10465441SEvalZero
255*10465441SEvalZero return (x);
256*10465441SEvalZero }
257*10465441SEvalZero
258*10465441SEvalZero /**
259*10465441SEvalZero \brief Unsigned Saturate
260*10465441SEvalZero \details Saturates an unsigned value.
261*10465441SEvalZero \param [in] value Value to be saturated
262*10465441SEvalZero \param [in] sat Bit position to saturate to (0..31)
263*10465441SEvalZero \return Saturated value
264*10465441SEvalZero */
__USAT(uint32_t value,uint32_t sat)265*10465441SEvalZero __ALWAYS_INLINE uint32_t __USAT(uint32_t value, uint32_t sat)
266*10465441SEvalZero {
267*10465441SEvalZero uint32_t result;
268*10465441SEvalZero
269*10465441SEvalZero if ((((0xFFFFFFFF >> sat) << sat) & value) != 0)
270*10465441SEvalZero {
271*10465441SEvalZero result = 0xFFFFFFFF >> (32 - sat);
272*10465441SEvalZero }
273*10465441SEvalZero else
274*10465441SEvalZero {
275*10465441SEvalZero result = value;
276*10465441SEvalZero }
277*10465441SEvalZero
278*10465441SEvalZero return (result);
279*10465441SEvalZero }
280*10465441SEvalZero
281*10465441SEvalZero /**
282*10465441SEvalZero \brief Unsigned Saturate for internal use
283*10465441SEvalZero \details Saturates an unsigned value, should not call directly.
284*10465441SEvalZero \param [in] value Value to be saturated
285*10465441SEvalZero \param [in] sat Bit position to saturate to (0..31)
286*10465441SEvalZero \return Saturated value
287*10465441SEvalZero */
__IUSAT(uint32_t value,uint32_t sat)288*10465441SEvalZero __ALWAYS_INLINE uint32_t __IUSAT(uint32_t value, uint32_t sat)
289*10465441SEvalZero {
290*10465441SEvalZero uint32_t result;
291*10465441SEvalZero
292*10465441SEvalZero if (value & 0x80000000) /* only overflow set bit-31 */
293*10465441SEvalZero {
294*10465441SEvalZero result = 0;
295*10465441SEvalZero }
296*10465441SEvalZero else if ((((0xFFFFFFFF >> sat) << sat) & value) != 0)
297*10465441SEvalZero {
298*10465441SEvalZero result = 0xFFFFFFFF >> (32 - sat);
299*10465441SEvalZero }
300*10465441SEvalZero else
301*10465441SEvalZero {
302*10465441SEvalZero result = value;
303*10465441SEvalZero }
304*10465441SEvalZero
305*10465441SEvalZero return (result);
306*10465441SEvalZero }
307*10465441SEvalZero
308*10465441SEvalZero /**
309*10465441SEvalZero \brief Rotate Right with Extend
310*10465441SEvalZero \details This function moves each bit of a bitstring right by one bit.
311*10465441SEvalZero The carry input is shifted in at the left end of the bitstring.
312*10465441SEvalZero \note carry input will always 0.
313*10465441SEvalZero \param [in] op1 Value to rotate
314*10465441SEvalZero \return Rotated value
315*10465441SEvalZero */
__RRX(uint32_t op1)316*10465441SEvalZero __ALWAYS_INLINE uint32_t __RRX(uint32_t op1)
317*10465441SEvalZero {
318*10465441SEvalZero #if (__CK80X >= 2)
319*10465441SEvalZero uint32_t res = 0;
320*10465441SEvalZero __ASM volatile("bgeni t0, 31\n\t"
321*10465441SEvalZero "lsri %0, 1\n\t"
322*10465441SEvalZero "movt %1, t0\n\t"
323*10465441SEvalZero "or %1, %1, %0\n\t"
324*10465441SEvalZero : "=r"(op1), "=r"(res): "0"(op1), "1"(res): "t0");
325*10465441SEvalZero return res;
326*10465441SEvalZero #else
327*10465441SEvalZero uint32_t res = 0;
328*10465441SEvalZero __ASM volatile("movi r7, 0\n\t"
329*10465441SEvalZero "bseti r7, 31\n\t"
330*10465441SEvalZero "lsri %0, 1\n\t"
331*10465441SEvalZero "bf 1f\n\t"
332*10465441SEvalZero "mov %1, r7\n\t"
333*10465441SEvalZero "1:\n\t"
334*10465441SEvalZero "or %1, %1, %0\n\t"
335*10465441SEvalZero : "=r"(op1), "=r"(res): "0"(op1), "1"(res): "r7");
336*10465441SEvalZero return res;
337*10465441SEvalZero #endif
338*10465441SEvalZero }
339*10465441SEvalZero
340*10465441SEvalZero /**
341*10465441SEvalZero \brief LDRT Unprivileged (8 bit)
342*10465441SEvalZero \details Executes a Unprivileged LDRT instruction for 8 bit value.
343*10465441SEvalZero \param [in] addr Pointer to location
344*10465441SEvalZero \return value of type uint8_t at (*ptr)
345*10465441SEvalZero */
__LDRBT(volatile uint8_t * addr)346*10465441SEvalZero __ALWAYS_INLINE uint8_t __LDRBT(volatile uint8_t *addr)
347*10465441SEvalZero {
348*10465441SEvalZero uint32_t result;
349*10465441SEvalZero //#warning "__LDRBT"
350*10465441SEvalZero __ASM volatile("ldb %0, (%1, 0)" : "=r"(result) : "r"(addr));
351*10465441SEvalZero return ((uint8_t) result); /* Add explicit type cast here */
352*10465441SEvalZero }
353*10465441SEvalZero
354*10465441SEvalZero
355*10465441SEvalZero /**
356*10465441SEvalZero \brief LDRT Unprivileged (16 bit)
357*10465441SEvalZero \details Executes a Unprivileged LDRT instruction for 16 bit values.
358*10465441SEvalZero \param [in] addr Pointer to location
359*10465441SEvalZero \return value of type uint16_t at (*ptr)
360*10465441SEvalZero */
__LDRHT(volatile uint16_t * addr)361*10465441SEvalZero __ALWAYS_INLINE uint16_t __LDRHT(volatile uint16_t *addr)
362*10465441SEvalZero {
363*10465441SEvalZero uint32_t result;
364*10465441SEvalZero
365*10465441SEvalZero //#warning "__LDRHT"
366*10465441SEvalZero __ASM volatile("ldh %0, (%1, 0)" : "=r"(result) : "r"(addr));
367*10465441SEvalZero return ((uint16_t) result); /* Add explicit type cast here */
368*10465441SEvalZero }
369*10465441SEvalZero
370*10465441SEvalZero
371*10465441SEvalZero /**
372*10465441SEvalZero \brief LDRT Unprivileged (32 bit)
373*10465441SEvalZero \details Executes a Unprivileged LDRT instruction for 32 bit values.
374*10465441SEvalZero \param [in] addr Pointer to location
375*10465441SEvalZero \return value of type uint32_t at (*ptr)
376*10465441SEvalZero */
__LDRT(volatile uint32_t * addr)377*10465441SEvalZero __ALWAYS_INLINE uint32_t __LDRT(volatile uint32_t *addr)
378*10465441SEvalZero {
379*10465441SEvalZero uint32_t result;
380*10465441SEvalZero
381*10465441SEvalZero //#warning "__LDRT"
382*10465441SEvalZero __ASM volatile("ldw %0, (%1, 0)" : "=r"(result) : "r"(addr));
383*10465441SEvalZero return (result);
384*10465441SEvalZero }
385*10465441SEvalZero
386*10465441SEvalZero
387*10465441SEvalZero /**
388*10465441SEvalZero \brief STRT Unprivileged (8 bit)
389*10465441SEvalZero \details Executes a Unprivileged STRT instruction for 8 bit values.
390*10465441SEvalZero \param [in] value Value to store
391*10465441SEvalZero \param [in] addr Pointer to location
392*10465441SEvalZero */
__STRBT(uint8_t value,volatile uint8_t * addr)393*10465441SEvalZero __ALWAYS_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr)
394*10465441SEvalZero {
395*10465441SEvalZero //#warning "__STRBT"
396*10465441SEvalZero __ASM volatile("stb %1, (%0, 0)" :: "r"(addr), "r"((uint32_t)value) : "memory");
397*10465441SEvalZero }
398*10465441SEvalZero
399*10465441SEvalZero
400*10465441SEvalZero /**
401*10465441SEvalZero \brief STRT Unprivileged (16 bit)
402*10465441SEvalZero \details Executes a Unprivileged STRT instruction for 16 bit values.
403*10465441SEvalZero \param [in] value Value to store
404*10465441SEvalZero \param [in] addr Pointer to location
405*10465441SEvalZero */
__STRHT(uint16_t value,volatile uint16_t * addr)406*10465441SEvalZero __ALWAYS_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr)
407*10465441SEvalZero {
408*10465441SEvalZero //#warning "__STRHT"
409*10465441SEvalZero __ASM volatile("sth %1, (%0, 0)" :: "r"(addr), "r"((uint32_t)value) : "memory");
410*10465441SEvalZero }
411*10465441SEvalZero
412*10465441SEvalZero
413*10465441SEvalZero /**
414*10465441SEvalZero \brief STRT Unprivileged (32 bit)
415*10465441SEvalZero \details Executes a Unprivileged STRT instruction for 32 bit values.
416*10465441SEvalZero \param [in] value Value to store
417*10465441SEvalZero \param [in] addr Pointer to location
418*10465441SEvalZero */
__STRT(uint32_t value,volatile uint32_t * addr)419*10465441SEvalZero __ALWAYS_INLINE void __STRT(uint32_t value, volatile uint32_t *addr)
420*10465441SEvalZero {
421*10465441SEvalZero //#warning "__STRT"
422*10465441SEvalZero __ASM volatile("stw %1, (%0, 0)" :: "r"(addr), "r"(value) : "memory");
423*10465441SEvalZero }
424*10465441SEvalZero
425*10465441SEvalZero /*@}*/ /* end of group CSI_Core_InstructionInterface */
426*10465441SEvalZero
427*10465441SEvalZero
428*10465441SEvalZero /* ########################## FPU functions #################################### */
429*10465441SEvalZero
430*10465441SEvalZero /**
431*10465441SEvalZero \brief get FPU type
432*10465441SEvalZero \details returns the FPU type, always 0.
433*10465441SEvalZero \returns
434*10465441SEvalZero - \b 0: No FPU
435*10465441SEvalZero - \b 1: Single precision FPU
436*10465441SEvalZero - \b 2: Double + Single precision FPU
437*10465441SEvalZero */
__get_FPUType(void)438*10465441SEvalZero __ALWAYS_INLINE uint32_t __get_FPUType(void)
439*10465441SEvalZero {
440*10465441SEvalZero uint32_t result;
441*10465441SEvalZero
442*10465441SEvalZero __ASM volatile("mfcr %0, cr<13, 0>" : "=r"(result));
443*10465441SEvalZero return 0;
444*10465441SEvalZero }
445*10465441SEvalZero
446*10465441SEvalZero
447*10465441SEvalZero #endif /* _CSI_INSTR_H_ */
448