CV_CoreInstr.c 13 KB

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