/** * @file * * @brief Information Required to Build RTEMS for a Particular Member * of the SPARC Family * * This file contains the information required to build * RTEMS for a particular member of the SPARC family. It does * this by setting variables to indicate which implementation * dependent features are present in a particular member * of the family. */ /* * COPYRIGHT (c) 1989-2011. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. */ #ifndef _RTEMS_SCORE_SPARC_H #define _RTEMS_SCORE_SPARC_H #include #ifdef __cplusplus extern "C" { #endif /* * * Currently recognized feature flags: * * + SPARC_HAS_FPU * 0 - no HW FPU * 1 - has HW FPU (assumed to be compatible w/90C602) * * + SPARC_HAS_BITSCAN * 0 - does not have scan instructions * 1 - has scan instruction (not currently implemented) * * + SPARC_NUMBER_OF_REGISTER_WINDOWS * 8 is the most common number supported by SPARC implementations. * SPARC_PSR_CWP_MASK is derived from this value. */ /** * Some higher end SPARCs have a bitscan instructions. It would * be nice to take advantage of them. Right now, there is no * port to a CPU model with this feature and no (untested) code * that is based on this feature flag. */ #define SPARC_HAS_BITSCAN 0 /** * This should be OK until a port to a higher end SPARC processor * is made that has more than 8 register windows. If this cannot * be determined based on multilib settings (v7/v8/v9), then the * cpu_asm.S code that depends on this will have to move to libcpu. */ #define SPARC_NUMBER_OF_REGISTER_WINDOWS 8 /** * This macro indicates whether this multilib variation has hardware * floating point or not. We use the gcc cpp predefine _SOFT_FLOAT * to determine that. */ #if defined(_SOFT_FLOAT) #define SPARC_HAS_FPU 0 #else #define SPARC_HAS_FPU 1 #endif /** * This macro contains a string describing the multilib variant being * build. */ #if SPARC_HAS_FPU #define CPU_MODEL_NAME "w/FPU" #else #define CPU_MODEL_NAME "w/soft-float" #endif /** * Define the name of the CPU family. */ #define CPU_NAME "SPARC" /* * Miscellaneous constants */ /** * PSR masks and starting bit positions * * NOTE: Reserved bits are ignored. */ #if (SPARC_NUMBER_OF_REGISTER_WINDOWS == 8) #define SPARC_PSR_CWP_MASK 0x07 /* bits 0 - 4 */ #elif (SPARC_NUMBER_OF_REGISTER_WINDOWS == 16) #define SPARC_PSR_CWP_MASK 0x0F /* bits 0 - 4 */ #elif (SPARC_NUMBER_OF_REGISTER_WINDOWS == 32) #define SPARC_PSR_CWP_MASK 0x1F /* bits 0 - 4 */ #else #error "Unsupported number of register windows for this cpu" #endif /** This constant is a mask for the ET bits in the PSR. */ #define SPARC_PSR_ET_MASK 0x00000020 /* bit 5 */ /** This constant is a mask for the PS bits in the PSR. */ #define SPARC_PSR_PS_MASK 0x00000040 /* bit 6 */ /** This constant is a mask for the S bits in the PSR. */ #define SPARC_PSR_S_MASK 0x00000080 /* bit 7 */ /** This constant is a mask for the PIL bits in the PSR. */ #define SPARC_PSR_PIL_MASK 0x00000F00 /* bits 8 - 11 */ /** This constant is a mask for the EF bits in the PSR. */ #define SPARC_PSR_EF_MASK 0x00001000 /* bit 12 */ /** This constant is a mask for the EC bits in the PSR. */ #define SPARC_PSR_EC_MASK 0x00002000 /* bit 13 */ /** This constant is a mask for the ICC bits in the PSR. */ #define SPARC_PSR_ICC_MASK 0x00F00000 /* bits 20 - 23 */ /** This constant is a mask for the VER bits in the PSR. */ #define SPARC_PSR_VER_MASK 0x0F000000 /* bits 24 - 27 */ /** This constant is a mask for the IMPL bits in the PSR. */ #define SPARC_PSR_IMPL_MASK 0xF0000000 /* bits 28 - 31 */ /** This constant is the starting bit position of the CWP in the PSR. */ #define SPARC_PSR_CWP_BIT_POSITION 0 /* bits 0 - 4 */ /** This constant is the starting bit position of the ET in the PSR. */ #define SPARC_PSR_ET_BIT_POSITION 5 /* bit 5 */ /** This constant is the starting bit position of the PS in the PSR. */ #define SPARC_PSR_PS_BIT_POSITION 6 /* bit 6 */ /** This constant is the starting bit position of the S in the PSR. */ #define SPARC_PSR_S_BIT_POSITION 7 /* bit 7 */ /** This constant is the starting bit position of the PIL in the PSR. */ #define SPARC_PSR_PIL_BIT_POSITION 8 /* bits 8 - 11 */ /** This constant is the starting bit position of the EF in the PSR. */ #define SPARC_PSR_EF_BIT_POSITION 12 /* bit 12 */ /** This constant is the starting bit position of the EC in the PSR. */ #define SPARC_PSR_EC_BIT_POSITION 13 /* bit 13 */ /** This constant is the starting bit position of the ICC in the PSR. */ #define SPARC_PSR_ICC_BIT_POSITION 20 /* bits 20 - 23 */ /** This constant is the starting bit position of the VER in the PSR. */ #define SPARC_PSR_VER_BIT_POSITION 24 /* bits 24 - 27 */ /** This constant is the starting bit position of the IMPL in the PSR. */ #define SPARC_PSR_IMPL_BIT_POSITION 28 /* bits 28 - 31 */ #define LEON3_ASR17_PROCESSOR_INDEX_SHIFT 28 /* SPARC Software Trap number definitions */ #define SPARC_SWTRAP_SYSCALL 0 #define SPARC_SWTRAP_IRQDIS 9 #define SPARC_SWTRAP_IRQEN 10 #ifndef ASM /** * This macro is a standard nop instruction. */ #define nop() \ do { \ __asm__ volatile ( "nop" ); \ } while ( 0 ) /** * @brief Macro to obtain the PSR. * * This macro returns the current contents of the PSR register in @a _psr. */ #if defined(RTEMS_PARAVIRT) uint32_t _SPARC_Get_PSR( void ); #define sparc_get_psr( _psr ) \ (_psr) = _SPARC_Get_PSR() #else /* RTEMS_PARAVIRT */ #define sparc_get_psr( _psr ) \ do { \ (_psr) = 0; \ __asm__ volatile( "rd %%psr, %0" : "=r" (_psr) : "0" (_psr) ); \ } while ( 0 ) #endif /* RTEMS_PARAVIRT */ /** * @brief Macro to set the PSR. * * This macro sets the PSR register to the value in @a _psr. */ #if defined(RTEMS_PARAVIRT) void _SPARC_Set_PSR( uint32_t new_psr ); #define sparc_set_psr( _psr ) \ _SPARC_Set_PSR( _psr ) #else /* RTEMS_PARAVIRT */ #define sparc_set_psr( _psr ) \ do { \ __asm__ volatile ( "mov %0, %%psr " : "=r" ((_psr)) : "0" ((_psr)) ); \ nop(); \ nop(); \ nop(); \ } while ( 0 ) #endif /* RTEMS_PARAVIRT */ /** * @brief Macro to obtain the TBR. * * This macro returns the current contents of the TBR register in @a _tbr. */ #if defined(RTEMS_PARAVIRT) uint32_t _SPARC_Get_TBR( void ); #define sparc_get_tbr( _tbr ) \ (_tbr) = _SPARC_Get_TBR() #else /* RTEMS_PARAVIRT */ #define sparc_get_tbr( _tbr ) \ do { \ (_tbr) = 0; /* to avoid unitialized warnings */ \ __asm__ volatile( "rd %%tbr, %0" : "=r" (_tbr) : "0" (_tbr) ); \ } while ( 0 ) #endif /* RTEMS_PARAVIRT */ /** * @brief Macro to set the TBR. * * This macro sets the TBR register to the value in @a _tbr. */ #if defined(RTEMS_PARAVIRT) void _SPARC_Set_TBR( uint32_t new_tbr ); #define sparc_set_tbr( _tbr ) \ _SPARC_Set_TBR((_tbr)) #else /* RTEMS_PARAVIRT */ #define sparc_set_tbr( _tbr ) \ do { \ __asm__ volatile( "wr %0, 0, %%tbr" : "=r" (_tbr) : "0" (_tbr) ); \ } while ( 0 ) #endif /* RTEMS_PARAVIRT */ /** * @brief Macro to obtain the WIM. * * This macro returns the current contents of the WIM field in @a _wim. */ #define sparc_get_wim( _wim ) \ do { \ __asm__ volatile( "rd %%wim, %0" : "=r" (_wim) : "0" (_wim) ); \ } while ( 0 ) /** * @brief Macro to set the WIM. * * This macro sets the WIM field to the value in @a _wim. */ #define sparc_set_wim( _wim ) \ do { \ __asm__ volatile( "wr %0, %%wim" : "=r" (_wim) : "0" (_wim) ); \ nop(); \ nop(); \ nop(); \ } while ( 0 ) /** * @brief Macro to obtain the Y register. * * This macro returns the current contents of the Y register in @a _y. */ #define sparc_get_y( _y ) \ do { \ __asm__ volatile( "rd %%y, %0" : "=r" (_y) : "0" (_y) ); \ } while ( 0 ) /** * @brief Macro to set the Y register. * * This macro sets the Y register to the value in @a _y. */ #define sparc_set_y( _y ) \ do { \ __asm__ volatile( "wr %0, %%y" : "=r" (_y) : "0" (_y) ); \ } while ( 0 ) /** * @brief SPARC disable processor interrupts. * * This method is invoked to disable all maskable interrupts. * * @return This method returns the entire PSR contents. */ static inline uint32_t sparc_disable_interrupts(void) { register uint32_t psr __asm__("g1"); /* return value of trap handler */ __asm__ volatile ( "ta %1\n\t" : "=r" (psr) : "i" (SPARC_SWTRAP_IRQDIS)); return psr; } /** * @brief SPARC enable processor interrupts. * * This method is invoked to enable all maskable interrupts. * * @param[in] psr is the PSR returned by @ref sparc_disable_interrupts. */ static inline void sparc_enable_interrupts(uint32_t psr) { register uint32_t _psr __asm__("g1") = psr; /* input to trap handler */ __asm__ volatile ( "ta %0\n" :: "i" (SPARC_SWTRAP_IRQEN), "r" (_psr)); } /** * @brief SPARC exit through system call 1 * * This method is invoked to go into system error halt. The optional * arguments can be given to hypervisor, hardware debugger, simulator or * similar. * * System error mode is entered when taking a trap when traps have been * disabled. What happens when error mode is entered depends on the motherboard. * In a typical development systems the CPU relingish control to the debugger, * simulator, hypervisor or similar. The following steps are taken: * * 1. Going into system error mode by Software Trap 0 * 2. %g1=1 (syscall 1 - Exit) * 3. %g2=Primary exit code * 4. %g3=Secondary exit code. Dependends on %g2 exit type. * * This function never returns. * * @param[in] exitcode1 Primary exit code stored in CPU g2 register after exit * @param[in] exitcode2 Primary exit code stored in CPU g3 register after exit */ void sparc_syscall_exit(uint32_t exitcode1, uint32_t exitcode2) RTEMS_COMPILER_NO_RETURN_ATTRIBUTE; /** * @brief SPARC flash processor interrupts. * * This method is invoked to temporarily enable all maskable interrupts. * * @param[in] _psr is the PSR returned by @ref sparc_disable_interrupts. */ #define sparc_flash_interrupts( _psr ) \ do { \ sparc_enable_interrupts( (_psr) ); \ _psr = sparc_disable_interrupts(); \ } while ( 0 ) /** * @brief SPARC obtain interrupt level. * * This method is invoked to obtain the current interrupt disable level. * * @param[in] _level is the PSR returned by @ref sparc_disable_interrupts. */ #define sparc_get_interrupt_level( _level ) \ do { \ register uint32_t _psr_level = 0; \ \ sparc_get_psr( _psr_level ); \ (_level) = \ (_psr_level & SPARC_PSR_PIL_MASK) >> SPARC_PSR_PIL_BIT_POSITION; \ } while ( 0 ) static inline uint32_t _LEON3_Get_current_processor( void ) { uint32_t asr17; __asm__ volatile ( "rd %%asr17, %0" : "=&r" (asr17) ); return asr17 >> LEON3_ASR17_PROCESSOR_INDEX_SHIFT; } #endif #ifdef __cplusplus } #endif #endif /* _RTEMS_SCORE_SPARC_H */