| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- /*-----------------------------------------------------------------------------
- * Name: CV_CoreInstr.c
- * Purpose: CMSIS CORE validation tests implementation
- *-----------------------------------------------------------------------------
- * Copyright (c) 2017 ARM Limited. All rights reserved.
- *----------------------------------------------------------------------------*/
- #include "CV_Framework.h"
- #include "cmsis_cv.h"
- #if defined(__CORTEX_M)
- #elif defined(__CORTEX_A)
- #include "irq_ctrl.h"
- #else
- #error __CORTEX_M or __CORTEX_A must be defined!
- #endif
- /*-----------------------------------------------------------------------------
- * Test implementation
- *----------------------------------------------------------------------------*/
- /*-----------------------------------------------------------------------------
- * Test cases
- *----------------------------------------------------------------------------*/
- /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
- /**
- \brief Test case: TC_CoreInstr_NOP
- \details
- - Check if __NOP instrinsic is available
- - No real assertion is deployed, just a compile time check.
- */
- void TC_CoreInstr_NOP (void) {
- __NOP();
- ASSERT_TRUE(1U == 1U);
- }
- /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
- /**
- \brief Test case: TC_CoreInstr_REV
- \details
- - Check if __REV instrinsic swaps all bytes in a word.
- */
- void TC_CoreInstr_REV (void) {
- uint32_t result = __REV(0x47110815U);
- ASSERT_TRUE(result == 0x15081147U);
-
- result = __REV(0x80000000U);
- ASSERT_TRUE(result == 0x00000080U);
- result = __REV(0x00000080U);
- ASSERT_TRUE(result == 0x80000000U);
- }
- /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
- /**
- \brief Test case: TC_CoreInstr_REV16
- \details
- - Check if __REV16 instrinsic swaps the bytes in both halfwords independendly.
- */
- void TC_CoreInstr_REV16(void) {
- uint32_t result = __REV16(0x47110815U);
- ASSERT_TRUE(result == 0x11471508U);
- }
- /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
- /**
- \brief Test case: TC_CoreInstr_REVSH
- \details
- - Check if __REVSH instrinsic swaps bytes in a signed halfword keeping the sign.
- */
- void TC_CoreInstr_REVSH(void) {
- int16_t result = __REVSH(0x4711);
- ASSERT_TRUE(result == 0x1147);
- result = __REVSH((int16_t)0x8000);
- ASSERT_TRUE(result == 0x0080);
- result = __REVSH(0x0080);
- ASSERT_TRUE(result == (int16_t)0x8000);
- }
- /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
- /**
- \brief Test case: TC_CoreInstr_ROT
- \details
- - Check if __ROR instrinsic moves all bits as expected.
- */
- void TC_CoreInstr_ROR(void) {
- uint32_t result = __ROR(0x01U, 1U);
- ASSERT_TRUE(result == 0x80000000U);
- result = __ROR(0x80000000U, 1U);
- ASSERT_TRUE(result == 0x40000000U);
- result = __ROR(0x40000000U, 30U);
- ASSERT_TRUE(result == 0x00000001U);
- result = __ROR(0x01U, 32U);
- ASSERT_TRUE(result == 0x00000001U);
- result = __ROR(0x08154711U, 8U);
- ASSERT_TRUE(result == 0x11081547U);
- }
- /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
- /**
- \brief Test case: TC_CoreInstr_RBIT
- \details
- - Check if __RBIT instrinsic revserses the bit order of arbitrary words.
- */
- void TC_CoreInstr_RBIT (void) {
- uint32_t result = __RBIT(0xAAAAAAAAU);
- ASSERT_TRUE(result == 0x55555555U);
- result = __RBIT(0x55555555U);
- ASSERT_TRUE(result == 0xAAAAAAAAU);
-
- result = __RBIT(0x00000001U);
- ASSERT_TRUE(result == 0x80000000U);
-
- result = __RBIT(0x80000000U);
- ASSERT_TRUE(result == 0x00000001U);
-
- result = __RBIT(0xDEADBEEFU);
- ASSERT_TRUE(result == 0xF77DB57BU);
- }
- /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
- /**
- \brief Test case: TC_CoreInstr_CLZ
- \details
- - Check if __CLZ instrinsic counts leading zeros.
- */
- void TC_CoreInstr_CLZ (void) {
- uint32_t result = __CLZ(0x00U);
- ASSERT_TRUE(result == 32);
- result = __CLZ(0x00000001U);
- ASSERT_TRUE(result == 31);
- result = __CLZ(0x40000000U);
- ASSERT_TRUE(result == 1);
- result = __CLZ(0x80000000U);
- ASSERT_TRUE(result == 0);
- result = __CLZ(0xFFFFFFFFU);
- ASSERT_TRUE(result == 0);
- result = __CLZ(0x80000001U);
- ASSERT_TRUE(result == 0);
- }
- /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
- #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
- (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
- (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
- (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \
- (defined(__CORTEX_A) ) )
-
- /// Exclusive byte value
- static volatile uint8_t TC_CoreInstr_Exclusives_byte = 0x47U;
- /// Exclusive halfword value
- static volatile uint16_t TC_CoreInstr_Exclusives_hword = 0x0815U;
- /// Exclusive word value
- static volatile uint32_t TC_CoreInstr_Exclusives_word = 0x08154711U;
- /**
- \brief Interrupt function for TC_CoreInstr_Exclusives
- \details
- The interrupt manipulates all the global data
- which disrupts the exclusive sequences in the test
- */
- static void TC_CoreInstr_ExclusivesIRQHandler(void) {
- const uint8_t b = __LDREXB(&TC_CoreInstr_Exclusives_byte);
- __STREXB((uint8_t)~b, &TC_CoreInstr_Exclusives_byte);
- const uint16_t hw = __LDREXH(&TC_CoreInstr_Exclusives_hword);
- __STREXH((uint16_t)~hw, &TC_CoreInstr_Exclusives_hword);
- const uint32_t w = __LDREXW(&TC_CoreInstr_Exclusives_word);
- __STREXW((uint32_t)~w, &TC_CoreInstr_Exclusives_word);
- }
- /**
- \brief Helper function for TC_CoreInstr_Exclusives to enable test interrupt.
- \details
- This helper function implements interrupt enabling according to target
- architecture, i.e. Cortex-A or Cortex-M.
- */
- static void TC_CoreInstr_ExclusivesIRQEnable(void) {
- #if defined(__CORTEX_M)
- TST_IRQHandler = TC_CoreInstr_ExclusivesIRQHandler;
- NVIC_EnableIRQ(WDT_IRQn);
- #elif defined(__CORTEX_A)
- IRQ_SetHandler(SGI0_IRQn, TC_CoreInstr_ExclusivesIRQHandler);
- IRQ_Enable(SGI0_IRQn);
- #else
- #error __CORTEX_M or __CORTEX_A must be defined!
- #endif
- __enable_irq();
- }
- /**
- \brief Helper function for TC_CoreInstr_Exclusives to set test interrupt pending.
- \details
- This helper function implements set pending the test interrupt according to target
- architecture, i.e. Cortex-A or Cortex-M.
- */
- static void TC_CoreInstr_ExclusivesIRQPend(void) {
- #if defined(__CORTEX_M)
- NVIC_SetPendingIRQ(WDT_IRQn);
- #elif defined(__CORTEX_A)
- IRQ_SetPending(SGI0_IRQn);
- #else
- #error __CORTEX_M or __CORTEX_A must be defined!
- #endif
- for(uint32_t i = 10U; i > 0U; --i) {}
- }
- /**
- \brief Helper function for TC_CoreInstr_Exclusives to disable test interrupt.
- \details
- This helper function implements interrupt disabling according to target
- architecture, i.e. Cortex-A or Cortex-M.
- */
- static void TC_CoreInstr_ExclusivesIRQDisable(void) {
- __disable_irq();
- #if defined(__CORTEX_M)
- NVIC_DisableIRQ(WDT_IRQn);
- TST_IRQHandler = NULL;
- #elif defined(__CORTEX_A)
- IRQ_Disable(SGI0_IRQn);
- IRQ_SetHandler(SGI0_IRQn, NULL);
- #else
- #error __CORTEX_M or __CORTEX_A must be defined!
- #endif
- }
- /**
- \brief Test case: TC_CoreInstr_Exclusives
- \details
- Checks exclusive load and store instructions:
- - LDREXB, LDREXH, LDREXW
- - STREXB, STREXH, STREXW
- - CLREX
- */
- void TC_CoreInstr_Exclusives (void) {
- /* 1. Test exclusives without interruption */
- do {
- const uint8_t v = __LDREXB(&TC_CoreInstr_Exclusives_byte);
- ASSERT_TRUE(v == TC_CoreInstr_Exclusives_byte);
-
- const uint32_t result = __STREXB(v+1U, &TC_CoreInstr_Exclusives_byte);
- ASSERT_TRUE(result == 0U);
- ASSERT_TRUE(TC_CoreInstr_Exclusives_byte == v+1U);
- } while(0);
-
- do {
- const uint16_t v = __LDREXH(&TC_CoreInstr_Exclusives_hword);
- ASSERT_TRUE(v == TC_CoreInstr_Exclusives_hword);
-
- const uint32_t result = __STREXH(v+1U, &TC_CoreInstr_Exclusives_hword);
- ASSERT_TRUE(result == 0U);
- ASSERT_TRUE(TC_CoreInstr_Exclusives_hword == v+1U);
- } while(0);
-
- do {
- const uint32_t v = __LDREXW(&TC_CoreInstr_Exclusives_word);
- ASSERT_TRUE(v == TC_CoreInstr_Exclusives_word);
-
- const uint32_t result = __STREXW(v+1U, &TC_CoreInstr_Exclusives_word);
- ASSERT_TRUE(result == 0U);
- ASSERT_TRUE(TC_CoreInstr_Exclusives_word == v+1U);
- } while(0);
-
- /* 2. Test exclusives with clear */
- do {
- const uint8_t v = __LDREXB(&TC_CoreInstr_Exclusives_byte);
- ASSERT_TRUE(v == TC_CoreInstr_Exclusives_byte);
-
- __CLREX();
-
- const uint32_t result = __STREXB(v+1U, &TC_CoreInstr_Exclusives_byte);
- ASSERT_TRUE(result == 1U);
- ASSERT_TRUE(TC_CoreInstr_Exclusives_byte == v);
- } while(0);
-
- do {
- const uint16_t v = __LDREXH(&TC_CoreInstr_Exclusives_hword);
- ASSERT_TRUE(v == TC_CoreInstr_Exclusives_hword);
-
- __CLREX();
-
- const uint32_t result = __STREXH(v+1U, &TC_CoreInstr_Exclusives_hword);
- ASSERT_TRUE(result == 1U);
- ASSERT_TRUE(TC_CoreInstr_Exclusives_hword == v);
- } while(0);
-
- do {
- const uint32_t v = __LDREXW(&TC_CoreInstr_Exclusives_word);
- ASSERT_TRUE(v == TC_CoreInstr_Exclusives_word);
-
- __CLREX();
-
- const uint32_t result = __STREXW(v+1U, &TC_CoreInstr_Exclusives_word);
- ASSERT_TRUE(result == 1U);
- ASSERT_TRUE(TC_CoreInstr_Exclusives_word == v);
- } while(0);
-
- /* 3. Test exclusives with interruption */
-
- TC_CoreInstr_ExclusivesIRQEnable();
-
- do {
- const uint8_t v = __LDREXB(&TC_CoreInstr_Exclusives_byte);
- ASSERT_TRUE(v == TC_CoreInstr_Exclusives_byte);
-
- TC_CoreInstr_ExclusivesIRQPend();
-
- const uint32_t result = __STREXB(v+1U, &TC_CoreInstr_Exclusives_byte);
- ASSERT_TRUE(result == 1U);
-
- const uint8_t iv = ~v;
- ASSERT_TRUE(iv == TC_CoreInstr_Exclusives_byte);
- } while(0);
-
- do {
- const uint16_t v = __LDREXH(&TC_CoreInstr_Exclusives_hword);
- ASSERT_TRUE(v == TC_CoreInstr_Exclusives_hword);
-
- TC_CoreInstr_ExclusivesIRQPend();
-
- const uint32_t result = __STREXH(v+1U, &TC_CoreInstr_Exclusives_hword);
- ASSERT_TRUE(result == 1U);
-
- const uint16_t iv = ~v;
- ASSERT_TRUE(iv == TC_CoreInstr_Exclusives_hword);
- } while(0);
-
- do {
- const uint32_t v = __LDREXW(&TC_CoreInstr_Exclusives_word);
- ASSERT_TRUE(v == TC_CoreInstr_Exclusives_word);
-
- TC_CoreInstr_ExclusivesIRQPend();
-
- const uint32_t result = __STREXW(v+1U, &TC_CoreInstr_Exclusives_word);
- ASSERT_TRUE(result == 1U);
-
- const uint32_t iv = ~v;
- ASSERT_TRUE(iv == TC_CoreInstr_Exclusives_word);
- } while(0);
-
- TC_CoreInstr_ExclusivesIRQDisable();
- }
- #endif
- /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
- /**
- \brief Test case: TC_CoreInstr_SSAT
- \details
- - Check if __SSAT instrinsic saturates signed integer values.
- */
- void TC_CoreInstr_SSAT (void) {
- int32_t result = __SSAT(INT32_MAX, 32U);
- ASSERT_TRUE(result == INT32_MAX);
- result = __SSAT(INT32_MAX, 16U);
- ASSERT_TRUE(result == INT16_MAX);
- result = __SSAT(INT32_MAX, 8U);
- ASSERT_TRUE(result == INT8_MAX);
-
- result = __SSAT(INT32_MAX, 1U);
- ASSERT_TRUE(result == 0);
- result = __SSAT(INT32_MIN, 32U);
- ASSERT_TRUE(result == INT32_MIN);
- result = __SSAT(INT32_MIN, 16U);
- ASSERT_TRUE(result == INT16_MIN);
- result = __SSAT(INT32_MIN, 8U);
- ASSERT_TRUE(result == INT8_MIN);
- result = __SSAT(INT32_MIN, 1U);
- ASSERT_TRUE(result == -1);
- }
- /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
- /**
- \brief Test case: TC_CoreInstr_USAT
- \details
- - Check if __USAT instrinsic saturates unsigned integer values.
- */
- void TC_CoreInstr_USAT (void) {
- uint32_t result = __USAT(INT32_MAX, 31U);
- ASSERT_TRUE(result == (UINT32_MAX>>1U));
- result = __USAT(INT32_MAX, 16U);
- ASSERT_TRUE(result == UINT16_MAX);
- result = __USAT(INT32_MAX, 8U);
- ASSERT_TRUE(result == UINT8_MAX);
- result = __USAT(INT32_MAX, 0U);
- ASSERT_TRUE(result == 0U);
- result = __USAT(INT32_MIN, 31U);
- ASSERT_TRUE(result == 0U);
- result = __USAT(INT32_MIN, 16U);
- ASSERT_TRUE(result == 0U);
- result = __USAT(INT32_MIN, 8U);
- ASSERT_TRUE(result == 0U);
- result = __USAT(INT32_MIN, 0U);
- ASSERT_TRUE(result == 0U);
- }
|