]> begriffs open source - cmsis/blob - CMSIS/CoreValidation/Source/CV_CoreInstr.c
CoreValidation: Fixed/enhanced core and intrinsic function tests.
[cmsis] / CMSIS / CoreValidation / Source / CV_CoreInstr.c
1 /*-----------------------------------------------------------------------------
2  *      Name:         CV_CoreInstr.c 
3  *      Purpose:      CMSIS CORE validation tests implementation
4  *-----------------------------------------------------------------------------
5  *      Copyright (c) 2017 ARM Limited. All rights reserved.
6  *----------------------------------------------------------------------------*/
7
8 #include "CV_Framework.h"
9 #include "cmsis_cv.h"
10
11 #if defined(__CORTEX_M)
12 #elif defined(__CORTEX_A)
13 #include "irq_ctrl.h"
14 #else
15 #error __CORTEX_M or __CORTEX_A must be defined!
16 #endif
17
18 /*-----------------------------------------------------------------------------
19  *      Test implementation
20  *----------------------------------------------------------------------------*/
21
22 /*-----------------------------------------------------------------------------
23  *      Test cases
24  *----------------------------------------------------------------------------*/
25
26 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
27 /**
28 \brief Test case: TC_CoreInstr_NOP
29 \details
30 - Check if __NOP instrinsic is available
31 - No real assertion is deployed, just a compile time check.
32 */
33 void TC_CoreInstr_NOP (void) {
34   __NOP();
35   ASSERT_TRUE(1U == 1U);
36 }
37
38 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
39 /**
40 \brief Test case: TC_CoreInstr_REV
41 \details
42 - Check if __REV instrinsic swaps all bytes in a word.
43 */
44 void TC_CoreInstr_REV (void) {
45   uint32_t result = __REV(0x47110815U);
46   ASSERT_TRUE(result == 0x15081147U);
47   
48   result = __REV(0x80000000U);
49   ASSERT_TRUE(result == 0x00000080U);
50
51   result = __REV(0x00000080U);
52   ASSERT_TRUE(result == 0x80000000U);
53 }
54
55 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
56 /**
57 \brief Test case: TC_CoreInstr_REV16
58 \details
59 - Check if __REV16 instrinsic swaps the bytes in both halfwords independendly.
60 */
61 void TC_CoreInstr_REV16(void) {
62   uint32_t result = __REV16(0x47110815U);
63   ASSERT_TRUE(result == 0x11471508U); 
64 }
65
66 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
67 /**
68 \brief Test case: TC_CoreInstr_REVSH
69 \details
70 - Check if __REVSH instrinsic swaps bytes in a signed halfword keeping the sign.
71 */
72 void TC_CoreInstr_REVSH(void) {
73   int16_t result = __REVSH(0x4711);
74   ASSERT_TRUE(result == 0x1147);
75
76   result = __REVSH((int16_t)0x8000);
77   ASSERT_TRUE(result == 0x0080);
78
79   result = __REVSH(0x0080);
80   ASSERT_TRUE(result == (int16_t)0x8000);
81 }
82
83 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
84 /**
85 \brief Test case: TC_CoreInstr_ROT
86 \details
87 - Check if __ROR instrinsic moves all bits as expected.
88 */
89 void TC_CoreInstr_ROR(void) {
90   uint32_t result = __ROR(0x01U, 1U);
91   ASSERT_TRUE(result == 0x80000000U);
92
93   result = __ROR(0x80000000U, 1U);
94   ASSERT_TRUE(result == 0x40000000U);
95
96   result = __ROR(0x40000000U, 30U);
97   ASSERT_TRUE(result == 0x00000001U);
98
99   result = __ROR(0x01U, 32U);
100   ASSERT_TRUE(result == 0x00000001U);
101
102   result = __ROR(0x08154711U, 8U);
103   ASSERT_TRUE(result == 0x11081547U);
104 }
105
106 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
107 /**
108 \brief Test case: TC_CoreInstr_RBIT
109 \details
110 - Check if __RBIT instrinsic revserses the bit order of arbitrary words.
111 */
112 void TC_CoreInstr_RBIT (void) {
113   uint32_t result = __RBIT(0xAAAAAAAAU);
114   ASSERT_TRUE(result == 0x55555555U);
115
116   result = __RBIT(0x55555555U);
117   ASSERT_TRUE(result == 0xAAAAAAAAU);
118   
119   result = __RBIT(0x00000001U);
120   ASSERT_TRUE(result == 0x80000000U);
121   
122   result = __RBIT(0x80000000U); 
123   ASSERT_TRUE(result == 0x00000001U);
124   
125   result = __RBIT(0xDEADBEEFU); 
126   ASSERT_TRUE(result == 0xF77DB57BU);
127 }
128
129 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
130 /**
131 \brief Test case: TC_CoreInstr_CLZ
132 \details
133 - Check if __CLZ instrinsic counts leading zeros.
134 */
135 void TC_CoreInstr_CLZ (void) {
136   uint32_t result = __CLZ(0x00U);
137   ASSERT_TRUE(result == 32);
138
139   result = __CLZ(0x00000001U);
140   ASSERT_TRUE(result == 31);
141
142   result = __CLZ(0x40000000U);
143   ASSERT_TRUE(result == 1);
144
145   result = __CLZ(0x80000000U);
146   ASSERT_TRUE(result == 0);
147
148   result = __CLZ(0xFFFFFFFFU);
149   ASSERT_TRUE(result == 0);
150
151   result = __CLZ(0x80000001U);
152   ASSERT_TRUE(result == 0);
153 }
154
155 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
156 #if ((defined (__ARM_ARCH_7M__      ) && (__ARM_ARCH_7M__      == 1)) || \
157      (defined (__ARM_ARCH_7EM__     ) && (__ARM_ARCH_7EM__     == 1)) || \
158      (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
159      (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \
160      (defined(__CORTEX_A)                                           )    )
161   
162 /// Exclusive byte value
163 static volatile uint8_t TC_CoreInstr_Exclusives_byte = 0x47U;
164
165 /// Exclusive halfword value
166 static volatile uint16_t TC_CoreInstr_Exclusives_hword = 0x0815U;
167
168 /// Exclusive word value
169 static volatile uint32_t TC_CoreInstr_Exclusives_word = 0x08154711U;
170
171 /** 
172 \brief Interrupt function for TC_CoreInstr_Exclusives
173 \details
174 The interrupt manipulates all the global data
175 which disrupts the exclusive sequences in the test
176 */
177 static void TC_CoreInstr_ExclusivesIRQHandler(void) {
178   const uint8_t b = __LDREXB(&TC_CoreInstr_Exclusives_byte);
179   __STREXB((uint8_t)~b, &TC_CoreInstr_Exclusives_byte);
180   const uint16_t hw = __LDREXH(&TC_CoreInstr_Exclusives_hword);
181   __STREXH((uint16_t)~hw, &TC_CoreInstr_Exclusives_hword);
182   const uint32_t w = __LDREXW(&TC_CoreInstr_Exclusives_word);
183   __STREXW((uint32_t)~w, &TC_CoreInstr_Exclusives_word);
184 }
185
186 /** 
187 \brief Helper function for TC_CoreInstr_Exclusives to enable test interrupt.
188 \details
189 This helper function implements interrupt enabling according to target
190 architecture, i.e. Cortex-A or Cortex-M.
191 */
192 static void TC_CoreInstr_ExclusivesIRQEnable(void) {
193 #if defined(__CORTEX_M)
194   TST_IRQHandler = TC_CoreInstr_ExclusivesIRQHandler;
195   NVIC_EnableIRQ(WDT_IRQn);
196 #elif defined(__CORTEX_A)
197   IRQ_SetHandler(SGI0_IRQn, TC_CoreInstr_ExclusivesIRQHandler);
198   IRQ_Enable(SGI0_IRQn);
199 #else
200   #error __CORTEX_M or __CORTEX_A must be defined!
201 #endif
202   __enable_irq();
203 }
204
205 /** 
206 \brief Helper function for TC_CoreInstr_Exclusives to set test interrupt pending.
207 \details
208 This helper function implements set pending the test interrupt according to target
209 architecture, i.e. Cortex-A or Cortex-M.
210 */
211 static void TC_CoreInstr_ExclusivesIRQPend(void) {
212 #if defined(__CORTEX_M)
213   NVIC_SetPendingIRQ(WDT_IRQn);
214 #elif defined(__CORTEX_A)
215   IRQ_SetPending(SGI0_IRQn);
216 #else
217   #error __CORTEX_M or __CORTEX_A must be defined!
218 #endif
219   for(uint32_t i = 10U; i > 0U; --i) {}
220 }
221
222 /** 
223 \brief Helper function for TC_CoreInstr_Exclusives to disable test interrupt.
224 \details
225 This helper function implements interrupt disabling according to target
226 architecture, i.e. Cortex-A or Cortex-M.
227 */
228 static void TC_CoreInstr_ExclusivesIRQDisable(void) {
229   __disable_irq();
230 #if defined(__CORTEX_M)
231   NVIC_DisableIRQ(WDT_IRQn);
232   TST_IRQHandler = NULL;
233 #elif defined(__CORTEX_A)
234   IRQ_Disable(SGI0_IRQn);
235   IRQ_SetHandler(SGI0_IRQn, NULL);
236 #else
237   #error __CORTEX_M or __CORTEX_A must be defined!
238 #endif
239 }
240
241 /**
242 \brief Test case: TC_CoreInstr_Exclusives
243 \details
244 Checks exclusive load and store instructions:
245 - LDREXB, LDREXH, LDREXW
246 - STREXB, STREXH, STREXW
247 - CLREX
248 */
249 void TC_CoreInstr_Exclusives (void) {
250   /* 1. Test exclusives without interruption */
251     do {
252       const uint8_t v = __LDREXB(&TC_CoreInstr_Exclusives_byte);
253       ASSERT_TRUE(v == TC_CoreInstr_Exclusives_byte);
254       
255       const uint32_t result = __STREXB(v+1U, &TC_CoreInstr_Exclusives_byte);
256       ASSERT_TRUE(result == 0U);
257       ASSERT_TRUE(TC_CoreInstr_Exclusives_byte == v+1U);
258     } while(0);
259     
260     do {
261      const uint16_t v = __LDREXH(&TC_CoreInstr_Exclusives_hword);
262       ASSERT_TRUE(v == TC_CoreInstr_Exclusives_hword);
263       
264       const uint32_t result = __STREXH(v+1U, &TC_CoreInstr_Exclusives_hword);
265       ASSERT_TRUE(result == 0U);
266       ASSERT_TRUE(TC_CoreInstr_Exclusives_hword == v+1U);
267     } while(0);
268       
269     do {
270       const uint32_t v = __LDREXW(&TC_CoreInstr_Exclusives_word);
271       ASSERT_TRUE(v == TC_CoreInstr_Exclusives_word);
272       
273       const uint32_t result = __STREXW(v+1U, &TC_CoreInstr_Exclusives_word);
274       ASSERT_TRUE(result == 0U);
275       ASSERT_TRUE(TC_CoreInstr_Exclusives_word == v+1U);
276     } while(0);
277   
278   /* 2. Test exclusives with clear */
279     do {
280       const uint8_t v = __LDREXB(&TC_CoreInstr_Exclusives_byte);
281       ASSERT_TRUE(v == TC_CoreInstr_Exclusives_byte);
282       
283       __CLREX();
284       
285       const uint32_t result = __STREXB(v+1U, &TC_CoreInstr_Exclusives_byte);
286       ASSERT_TRUE(result == 1U);
287       ASSERT_TRUE(TC_CoreInstr_Exclusives_byte == v);
288     } while(0);
289     
290     do {
291       const uint16_t v = __LDREXH(&TC_CoreInstr_Exclusives_hword);
292       ASSERT_TRUE(v == TC_CoreInstr_Exclusives_hword);
293       
294       __CLREX();
295       
296       const uint32_t result = __STREXH(v+1U, &TC_CoreInstr_Exclusives_hword);
297       ASSERT_TRUE(result == 1U);
298       ASSERT_TRUE(TC_CoreInstr_Exclusives_hword == v);
299     } while(0);
300       
301     do {
302       const uint32_t v = __LDREXW(&TC_CoreInstr_Exclusives_word);
303       ASSERT_TRUE(v == TC_CoreInstr_Exclusives_word);
304       
305       __CLREX();
306       
307       const uint32_t result = __STREXW(v+1U, &TC_CoreInstr_Exclusives_word);
308       ASSERT_TRUE(result == 1U);
309       ASSERT_TRUE(TC_CoreInstr_Exclusives_word == v);
310     } while(0);
311     
312   /* 3. Test exclusives with interruption */
313     
314     TC_CoreInstr_ExclusivesIRQEnable();
315     
316     do {
317       const uint8_t v = __LDREXB(&TC_CoreInstr_Exclusives_byte);
318       ASSERT_TRUE(v == TC_CoreInstr_Exclusives_byte);
319       
320       TC_CoreInstr_ExclusivesIRQPend();
321         
322       const uint32_t result = __STREXB(v+1U, &TC_CoreInstr_Exclusives_byte);
323       ASSERT_TRUE(result == 1U);
324       ASSERT_TRUE(TC_CoreInstr_Exclusives_byte == (uint8_t)~v);
325     } while(0);
326     
327     do {
328       const uint16_t v = __LDREXH(&TC_CoreInstr_Exclusives_hword);
329       ASSERT_TRUE(v == TC_CoreInstr_Exclusives_hword);
330       
331       TC_CoreInstr_ExclusivesIRQPend();
332       
333       const uint32_t result = __STREXH(v+1U, &TC_CoreInstr_Exclusives_hword);
334       ASSERT_TRUE(result == 1U);
335       ASSERT_TRUE(TC_CoreInstr_Exclusives_hword == (uint16_t)~v);
336     } while(0);
337       
338     do {
339       const uint32_t v = __LDREXW(&TC_CoreInstr_Exclusives_word);
340       ASSERT_TRUE(v == TC_CoreInstr_Exclusives_word);
341       
342       TC_CoreInstr_ExclusivesIRQPend();
343         
344       const uint32_t result = __STREXW(v+1U, &TC_CoreInstr_Exclusives_word);
345       ASSERT_TRUE(result == 1U);
346       ASSERT_TRUE(TC_CoreInstr_Exclusives_word == ~v);
347     } while(0);
348     
349     TC_CoreInstr_ExclusivesIRQDisable();
350 }
351 #endif
352
353 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
354 /**
355 \brief Test case: TC_CoreInstr_SSAT
356 \details
357 - Check if __SSAT instrinsic saturates signed integer values.
358 */
359 void TC_CoreInstr_SSAT (void) {
360   int32_t result = __SSAT(INT32_MAX, 32U);
361   ASSERT_TRUE(result == INT32_MAX);
362
363   result = __SSAT(INT32_MAX, 16U);
364   ASSERT_TRUE(result == INT16_MAX);
365
366   result = __SSAT(INT32_MAX, 8U);
367   ASSERT_TRUE(result == INT8_MAX);
368  
369   result = __SSAT(INT32_MAX, 1U);
370   ASSERT_TRUE(result == 0);
371
372   result = __SSAT(INT32_MIN, 32U);
373   ASSERT_TRUE(result == INT32_MIN);
374
375   result = __SSAT(INT32_MIN, 16U);
376   ASSERT_TRUE(result == INT16_MIN);
377
378   result = __SSAT(INT32_MIN, 8U);
379   ASSERT_TRUE(result == INT8_MIN);
380
381   result = __SSAT(INT32_MIN, 1U);
382   ASSERT_TRUE(result == -1);
383 }
384
385 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
386 /**
387 \brief Test case: TC_CoreInstr_USAT
388 \details
389 - Check if __USAT instrinsic saturates unsigned integer values.
390 */
391 void TC_CoreInstr_USAT (void) {
392   uint32_t result = __USAT(INT32_MAX, 31U);
393   ASSERT_TRUE(result == (UINT32_MAX>>1U));
394
395   result = __USAT(INT32_MAX, 16U);
396   ASSERT_TRUE(result == UINT16_MAX);
397
398   result = __USAT(INT32_MAX, 8U);
399   ASSERT_TRUE(result == UINT8_MAX);
400
401   result = __USAT(INT32_MAX, 0U);
402   ASSERT_TRUE(result == 0U);
403
404   result = __USAT(INT32_MIN, 31U);
405   ASSERT_TRUE(result == 0U);
406
407   result = __USAT(INT32_MIN, 16U);
408   ASSERT_TRUE(result == 0U);
409
410   result = __USAT(INT32_MIN, 8U);
411   ASSERT_TRUE(result == 0U);
412
413   result = __USAT(INT32_MIN, 0U);
414   ASSERT_TRUE(result == 0U);
415 }