attr.h

Go to the documentation of this file.
00001 
00041 #ifndef CPU_ATTR_H
00042 #define CPU_ATTR_H
00043 
00044 #include "detect.h"
00045 #include <cfg/compiler.h> /* for uintXX_t */
00046 #include <cfg/arch_config.h>  /* ARCH_EMUL */
00047 
00048 #include "appconfig.h" // CONFIG_FAST_MEM
00049 
00054 #define CPU_BIG_ENDIAN    0x1234
00055 #define CPU_LITTLE_ENDIAN 0x3412 /* Look twice, pal. This is not a bug. */
00056 /*\}*/
00057 
00059 #define CPU_HEADER(module)          PP_STRINGIZE(drv/PP_CAT3(module, _, CPU_ID).h)
00060 
00062 #define CPU_CSOURCE(module)         PP_STRINGIZE(drv/PP_CAT3(module, _, CPU_ID).c)
00063 
00064 
00065 #if CPU_I196
00066 
00067     #define NOP                     nop_instruction()
00068 
00069     #define CPU_REG_BITS            16
00070     #define CPU_REGS_CNT            16
00071     #define CPU_STACK_GROWS_UPWARD  0
00072     #define CPU_SP_ON_EMPTY_SLOT    0
00073     #define CPU_BYTE_ORDER          CPU_LITTLE_ENDIAN
00074     #define CPU_HARVARD     0
00075 
00076 #elif CPU_X86
00077 
00078     #define NOP                     asm volatile ("nop")
00079 
00080     #define CPU_REGS_CNT            7
00081     #define CPU_SAVED_REGS_CNT      7
00082     #define CPU_STACK_GROWS_UPWARD  0
00083     #define CPU_SP_ON_EMPTY_SLOT    0
00084     #define CPU_BYTE_ORDER          CPU_LITTLE_ENDIAN
00085     #define CPU_HARVARD     0
00086 
00087     #if CPU_X86_64
00088         #define CPU_REG_BITS    64
00089 
00090         #ifdef __WIN64__
00091             /* WIN64 is an IL32-P64 weirdo. */
00092             #define SIZEOF_LONG  4
00093         #endif
00094     #else
00095         #define CPU_REG_BITS    32
00096     #endif
00097 
00098 #elif CPU_ARM
00099 
00100     /* Register counts include SREG too */
00101     #define CPU_REG_BITS           32
00102     #define CPU_REGS_CNT           16
00103     #define CPU_SAVED_REGS_CNT     9
00104     #define CPU_STACK_GROWS_UPWARD 0
00105     #define CPU_SP_ON_EMPTY_SLOT   0
00106     #define CPU_HARVARD            0
00107 
00108     #ifdef __IAR_SYSTEMS_ICC__
00109         #warning Check CPU_BYTE_ORDER
00110         #define CPU_BYTE_ORDER (__BIG_ENDIAN__ ? CPU_BIG_ENDIAN : CPU_LITTLE_ENDIAN)
00111 
00112         #define NOP            __no_operation()
00113 
00114     #else /* GCC and compatibles */
00115 
00116         #if defined(__ARMEB__)
00117             #define CPU_BYTE_ORDER CPU_BIG_ENDIAN
00118         #elif defined(__ARMEL__)
00119             #define CPU_BYTE_ORDER CPU_LITTLE_ENDIAN
00120         #else
00121             #error Unable to detect ARM endianness!
00122         #endif
00123 
00124         #define NOP            asm volatile ("mov r0,r0" ::)
00125 
00138         #define CPU_REG_INIT_VALUE(reg) (reg == (CPU_SAVED_REGS_CNT - 1) ? 0x13 : 0)
00139 
00140         #if CONFIG_FAST_MEM
00141 
00149             #define FAST_FUNC __attribute__((section(".data")))
00150 
00156             #define FAST_RODATA __attribute__((section(".data")))
00157 
00158         #else // !CONFIG_FAST_MEM
00159             #define FAST_RODATA 
00160             #define FAST_FUNC 
00161         #endif
00162 
00166         #define ISR_FUNC __attribute__((interrupt))
00167 
00168     #endif /* !__IAR_SYSTEMS_ICC_ */
00169 
00170 #elif CPU_PPC
00171     #define NOP                 asm volatile ("nop" ::)
00172 
00173     /* Register counts include SREG too */
00174     #define CPU_REG_BITS           (CPU_PPC32 ? 32 : 64)
00175     #define CPU_REGS_CNT           FIXME
00176     #define CPU_SAVED_REGS_CNT     FIXME
00177     #define CPU_STACK_GROWS_UPWARD 0  //FIXME
00178     #define CPU_SP_ON_EMPTY_SLOT   0  //FIXME
00179     #define CPU_BYTE_ORDER         (__BIG_ENDIAN__ ? CPU_BIG_ENDIAN : CPU_LITTLE_ENDIAN)
00180     #define CPU_HARVARD            0
00181 
00182 #elif CPU_DSP56K
00183 
00184     #define NOP                     asm(nop)
00185 
00186     #define CPU_REG_BITS            16
00187     #define CPU_REGS_CNT            FIXME
00188     #define CPU_SAVED_REGS_CNT      8
00189     #define CPU_STACK_GROWS_UPWARD  1
00190     #define CPU_SP_ON_EMPTY_SLOT    0
00191     #define CPU_BYTE_ORDER          CPU_BIG_ENDIAN
00192     #define CPU_HARVARD     1
00193 
00194     /* Memory is word-addessed in the DSP56K */
00195     #define CPU_BITS_PER_CHAR  16
00196     #define SIZEOF_SHORT        1
00197     #define SIZEOF_INT          1
00198     #define SIZEOF_LONG         2
00199     #define SIZEOF_PTR          1
00200 
00201 #elif CPU_AVR
00202 
00203     #define NOP           asm volatile ("nop" ::)
00204 
00205     /* Register counts include SREG too */
00206     #define CPU_REG_BITS            8
00207     #define CPU_REGS_CNT           33
00208     #define CPU_SAVED_REGS_CNT     19
00209     #define CPU_STACK_GROWS_UPWARD  0
00210     #define CPU_SP_ON_EMPTY_SLOT    1
00211     #define CPU_BYTE_ORDER          CPU_LITTLE_ENDIAN
00212     #define CPU_HARVARD             1
00213 
00220     #define CPU_REG_INIT_VALUE(reg) (reg == 0 ? 0x80 : 0)
00221 
00222 #else
00223     #error No CPU_... defined.
00224 #endif
00225 
00227 #ifndef CPU_REG_INIT_VALUE
00228     #define CPU_REG_INIT_VALUE(reg)     0
00229 #endif
00230 
00231 
00232 #ifndef CPU_STACK_GROWS_UPWARD
00233     #error CPU_STACK_GROWS_UPWARD should have been defined to either 0 or 1
00234 #endif
00235 
00236 #ifndef CPU_SP_ON_EMPTY_SLOT
00237     #error CPU_SP_ON_EMPTY_SLOT should have been defined to either 0 or 1
00238 #endif
00239 
00240 /*
00241  * Support stack handling peculiarities of a few CPUs.
00242  *
00243  * Most processors let their stack grow downward and
00244  * keep SP pointing at the last pushed value.
00245  */
00246 #if !CPU_STACK_GROWS_UPWARD
00247     #if !CPU_SP_ON_EMPTY_SLOT
00248         /* Most microprocessors (x86, m68k...) */
00249         #define CPU_PUSH_WORD(sp, data) \
00250             do { *--(sp) = (data); } while (0)
00251         #define CPU_POP_WORD(sp) \
00252             (*(sp)++)
00253     #else
00254         /* AVR insanity */
00255         #define CPU_PUSH_WORD(sp, data) \
00256             do { *(sp)-- = (data); } while (0)
00257         #define CPU_POP_WORD(sp) \
00258             (*++(sp))
00259     #endif
00260 
00261 #else /* CPU_STACK_GROWS_UPWARD */
00262 
00263     #if !CPU_SP_ON_EMPTY_SLOT
00264         /* DSP56K and other weirdos */
00265         #define CPU_PUSH_WORD(sp, data) \
00266             do { *++(sp) = (cpustack_t)(data); } while (0)
00267         #define CPU_POP_WORD(sp) \
00268             (*(sp)--)
00269     #else
00270         #error I bet you cannot find a CPU like this
00271     #endif
00272 #endif
00273 
00274 
00275 #if CPU_DSP56K
00276     /*
00277      * DSP56k pushes both PC and SR to the stack in the JSR instruction, but
00278      * RTS discards SR while returning (it does not restore it). So we push
00279      * 0 to fake the same context.
00280      */
00281     #define CPU_PUSH_CALL_CONTEXT(sp, func) \
00282         do { \
00283             CPU_PUSH_WORD((sp), (func)); \
00284             CPU_PUSH_WORD((sp), 0x100); \
00285         } while (0);
00286 
00287 #elif CPU_AVR
00288     /*
00289      * In AVR, the addresses are pushed into the stack as little-endian, while
00290      * memory accesses are big-endian (actually, it's a 8-bit CPU, so there is
00291      * no natural endianess).
00292      */
00293     #define CPU_PUSH_CALL_CONTEXT(sp, func) \
00294         do { \
00295             uint16_t funcaddr = (uint16_t)(func); \
00296             CPU_PUSH_WORD((sp), funcaddr); \
00297             CPU_PUSH_WORD((sp), funcaddr>>8); \
00298         } while (0)
00299 
00300     /*
00301      * If the kernel is in idle-spinning, the processor executes:
00302      *
00303      * IRQ_ENABLE;
00304      * CPU_IDLE;
00305      * IRQ_DISABLE;
00306      *
00307      * IRQ_ENABLE is translated in asm as "sei" and IRQ_DISABLE as "cli".
00308      * We could define CPU_IDLE to expand to none, so the resulting
00309      * asm code would be:
00310      *
00311      * sei;
00312      * cli;
00313      *
00314      * But Atmel datasheet states:
00315      * "When using the SEI instruction to enable interrupts,
00316      * the instruction following SEI will be executed *before*
00317      * any pending interrupts", so "cli" is executed before any
00318      * pending interrupt with the result that IRQs will *NOT*
00319      * be enabled!
00320      * To ensure that IRQ will run a NOP is required.
00321      */
00322     #define CPU_IDLE NOP
00323 
00324 #else
00325     #define CPU_PUSH_CALL_CONTEXT(sp, func) \
00326         CPU_PUSH_WORD((sp), (cpustack_t)(func))
00327 #endif
00328 
00338 #ifndef CPU_IDLE
00339     #if defined(ARCH_EMUL) && (ARCH & ARCH_EMUL)
00340         /* This emulator hook should yield the CPU to the host.  */
00341         EXTERN_C_BEGIN
00342         void emul_idle(void);
00343         EXTERN_C_END
00344         #define CPU_IDLE emul_idle()
00345     #else /* !ARCH_EMUL */
00346         #define CPU_IDLE do { /* nothing */ } while (0)
00347     #endif /* !ARCH_EMUL */
00348 #endif /* !CPU_IDLE */
00349 
00350 #endif /* CPU_ATTR_H */