Spelling/grammar fixes.
[bertos.git] / compiler.h
1 /*!
2  * \file
3  * <!--
4  * Copyright 2003, 2004 Develer S.r.l. (http://www.develer.com/)
5  * Copyright 2001, 2002, 2003 Bernardo Innocenti <bernie@codewiz.org>
6  * This file is part of DevLib - See devlib/README for information.
7  * -->
8  *
9  * \version $Id$
10  *
11  * \author Bernardo Innocenti <bernie@develer.com>
12  *
13  * \brief Additional support macros for compiler independance
14  */
15
16 /*#*
17  *#* $Log$
18  *#* Revision 1.19  2004/08/25 14:12:08  rasky
19  *#* Aggiornato il comment block dei log RCS
20  *#*
21  *#* Revision 1.18  2004/08/24 16:32:37  bernie
22  *#* Document custom types.
23  *#*
24  *#* Revision 1.17  2004/08/24 13:32:14  bernie
25  *#* PP_CAT(), PP_STRINGIZE(): Move back to compiler.h to break circular dependency between cpu.h/compiler.h/macros.h;
26  *#* offsetof(), countof(): Move back to compiler.h to avoid including macros.h almost everywhere;
27  *#* Trim CVS log;
28  *#* Rename header guards;
29  *#* Don't include arch_config.h in compiler.h as it's not needed there.
30  *#*
31  *#* Revision 1.16  2004/08/14 19:37:57  rasky
32  *#* Merge da SC: macros.h, pool.h, BIT_CHANGE, nome dei processi, etc.
33  *#*
34  *#* Revision 1.15  2004/08/13 03:23:26  bernie
35  *#* Adjust a few MSVC tweaks from older projects.
36  *#*
37  *#* Revision 1.14  2004/08/10 06:56:29  bernie
38  *#* RESTRICT: New C99-like macro; STATIC_ASSERT: Fix warning for multiple invocation in one file.
39  *#*
40  *#* Revision 1.13  2004/08/02 20:20:29  aleph
41  *#* Merge from project_ks
42  *#*
43  *#* Revision 1.12  2004/08/01 01:21:17  bernie
44  *#* LIKELY(), UNLIKELY(): New compiler-specific macros.
45  *#*
46  *#* Revision 1.11  2004/07/30 14:34:10  rasky
47  *#* Vari fix per documentazione e commenti
48  *#* Aggiunte PP_CATn e STATIC_ASSERT
49  *#*
50  *#* Revision 1.10  2004/07/30 14:15:53  rasky
51  *#* Nuovo supporto unificato per detect della CPU
52  *#*
53  *#* Revision 1.9  2004/07/29 22:57:09  bernie
54  *#* vsprintf(): Remove prototype for backwards compatibility with GCC 3.4; ssize_t: Add definition for inferior compilers.
55  *#*/
56 #ifndef DEVLIB_COMPILER_H
57 #define DEVLIB_COMPILER_H
58
59 #include "cpu_detect.h"
60
61
62 #if defined __GNUC__ && defined __GNUC_MINOR__
63         #define GNUC_PREREQ(maj, min) \
64                 ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
65 #else
66         #define GNUC_PREREQ(maj, min) 0
67 #endif
68
69 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
70         #define COMPILER_C99      1
71 #else
72         #define COMPILER_C99      0
73 #endif
74
75
76 /*! Concatenate two different preprocessor tokens (allowing macros to expand) */
77 #define PP_CAT(x,y)         PP_CAT__(x,y)
78 #define PP_CAT__(x,y)       x ## y
79 #define PP_CAT3(x,y,z)      PP_CAT(PP_CAT(x,y),z)
80 #define PP_CAT4(x,y,z,w)    PP_CAT(PP_CAT3(x,y,z),w)
81 #define PP_CAT5(x,y,z,w,j)  PP_CAT(PP_CAT4(x,y,z,w),j)
82
83 /*! String-ize a token (allowing macros to expand) */
84 #define PP_STRINGIZE(x)     PP_STRINGIZE__(x)
85 #define PP_STRINGIZE__(x)   #x
86
87
88 #if defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__)
89         #pragma language=extended
90         #define INTERRUPT(x)  interrupt [x]
91         #define REGISTER      shortad
92         #define INLINE        /* unsupported */
93
94         /* Imported from <longjmp.h>. Unfortunately, we can't just include
95          * this header because it typedefs jmp_buf to be an array of chars.
96          * This would allow the compiler to place the buffer on an odd address.
97          * The CPU _should_ be able to perform word accesses to
98          * unaligned data, but there are *BUGS* in the 80196KC with
99          * some combinations of opcodes and addressing modes. One of
100          * these, "ST SP,[?GR]+" is used in the longjmp() implementation
101          * provided by the IAR compiler ANSI C library. When ?GR contains
102          * an odd address, surprisingly the CPU will copy the high order
103          * byte of the source operand (SP) in the low order byte of the
104          * destination operand (the memory location pointed to by ?GR).
105          *
106          * We also need to replace the library setjmp()/longjmp() with
107          * our own versions because the IAR implementation "forgets" to
108          * save the contents of local registers (?LR).
109          */
110         struct _JMP_BUF
111         {
112                 void *  sp;                             /* Stack pointer */
113                 void *  return_addr;    /* Return address */
114                 int             lr[6];                  /* 6 local registers */
115         };
116
117         typedef struct _JMP_BUF jmp_buf[1];
118
119         int setjmp(jmp_buf env);
120         void longjmp(jmp_buf env, int val);
121
122         /* Fake bool support */
123         #define true (1==1)
124         #define false (1!=1)
125         typedef unsigned char bool;
126
127 #elif defined(_MSC_VER) /* Win32 emulation support */
128
129         #include <setjmp.h>
130         #include <time.h> /* for time_t */
131
132         /* FIXME: I can't remember why exactly this was needed (NdBernie) */
133         #define float double
134
135         /* Fake bool support */
136         #ifndef __cplusplus
137                 #define true 1
138                 #define false 0
139                 typedef int bool;
140         #endif /* !__cplusplus */
141
142         /* These C99 functions are oddly named in MSVCRT32.lib */
143         #define snprintf _snprintf
144         #define vsnprintf _vsnprintf
145
146 #elif defined(__GNUC__)
147
148         /* GCC attributes */
149         #define FORMAT(type,fmt,first)  __attribute__((__format__(type, fmt, first)))
150         #define NORETURN                __attribute__((__noreturn__))
151         #define UNUSED(type,arg)        __attribute__((__unused__)) type arg
152         #define INLINE                  static inline __attribute__((__always_inline__))
153         #define LIKELY(x)               __builtin_expect((x), 1)
154         #define UNLIKELY(x)             __builtin_expect((x), 0)
155         #define RESTRICT                __restrict__
156         #if GNUC_PREREQ(3,1)
157                 #define DEPRECATED      __attribute__((__deprecated__))
158         #endif
159
160         #if CPU_X86
161
162                 /* hack to avoid conflicts with system type */
163                 #define sigset_t system_sigset_t
164                 #include <stddef.h>
165                 #include <setjmp.h>
166                 #include <stdbool.h>
167                 #undef system_sigset_t
168
169         #elif CPU_AVR
170
171                 #include <stddef.h>
172                 #include <stdbool.h>
173
174                 /* Missing printf-family functions in avr-libc/stdio.h */
175                 #include <stdarg.h>
176                 #include <avr/pgmspace.h>
177                 int vsprintf_P(char *buf, const char * PROGMEM fmt, va_list ap);
178
179                 /* Support for harvard architectures */
180                 #ifdef _PROGMEM
181                         #define PGM_READ_CHAR(s) pgm_read_byte(s)
182                         #define PGM_FUNC(x) x ## _P
183                         #define PGM_ATTR        PROGMEM
184                 #endif
185
186         #endif
187
188 #elif defined(__MWERKS__) && CPU_DSP56K
189
190         #include <stdint.h>
191         #include <stddef.h>
192         #include <stdbool.h>
193         #include <setjmp.h>
194
195         // CodeWarrior has size_t as built-in type, but does not define this symbol.
196         #define _SIZE_T_DEFINED
197
198 #else
199         #error unknown compiler
200 #endif
201
202
203 /* A few defaults for missing compiler features. */
204 #ifndef INLINE
205 #define INLINE                 static inline
206 #endif
207 #ifndef NORETURN
208 #define NORETURN               /* nothing */
209 #endif
210 #ifndef FORMAT
211 #define FORMAT(type,fmt,first) /* nothing */
212 #endif
213 #ifndef DEPRECATED
214 #define DEPRECATED             /* nothing */
215 #endif
216 #ifndef UNUSED
217 #define UNUSED(type,arg)       type arg
218 #endif
219 #ifndef REGISTER
220 #define REGISTER               /* nothing */
221 #endif
222 #ifndef INTERRUPT
223 #define INTERRUPT(x)           ERROR_NOT_IMPLEMENTED
224 #endif
225 #ifndef LIKELY
226 #define LIKELY(x)              x
227 #endif
228 #ifndef UNLIKELY
229 #define UNLIKELY(x)            x
230 #endif
231 #ifndef RESTRICT
232 #define RESTRICT
233 #endif
234
235 /* Support for harvard architectures */
236 #ifndef PSTR
237 #define PSTR            /* nothing */
238 #endif
239 #ifndef PGM_READ_CHAR
240 #define PGM_READ_CHAR(s) (*(s))
241 #endif
242 #ifndef PGM_FUNC
243 #define PGM_FUNC(x) x
244 #endif
245 #ifndef PGM_ATTR
246 #define PGM_ATTR        /* nothing */
247 #endif
248
249
250 /* Misc definitions */
251 #ifndef NULL
252 #define NULL  (void *)0
253 #endif
254 #ifndef EOF
255 #define EOF   (-1)
256 #endif
257
258
259 /* Support for hybrid C/C++ applications. */
260 #ifdef __cplusplus
261         #define EXTERN_C_BEGIN  extern "C" {
262         #define EXTERN_C_END    }
263 #else
264         #define EXTERN_C_BEGIN  /* nothing */
265         #define EXTERN_C_END    /* nothing */
266 #endif
267
268
269 /*
270  * Standard type definitions
271  * These should be in <sys/types.h>, but many compilers lack them.
272  */
273 #if !(defined(size_t) || defined(_SIZE_T_DEFINED))
274         typedef unsigned int size_t;
275         typedef int ssize_t;
276 #endif
277 #if !(defined(_TIME_T_DEFINED) || defined(__time_t_defined))
278         typedef long time_t;
279 #endif /* _TIME_T_DEFINED || __time_t_defined */
280
281 /*! Storage for pointers and integers */
282 /* FIXME: turn this into a typedef? */
283 #define IPTR void *
284
285 typedef long utime_t;            /*!< Type for time expressed in microseconds */
286 typedef unsigned char sig_t;     /*!< Type for signal bits */
287 typedef unsigned char sigset_t;  /*!< Type for signal masks */
288 typedef unsigned char page_t;    /*!< Type for banked memory pages */
289
290 #if (defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__))
291         /*!
292          * \name ISO C99 fixed-size types
293          *
294          * These should be in <stdint.h>, but many compilers lack them.
295          * \{
296          */
297         typedef signed char         int8_t;
298         typedef short int           int16_t;
299         typedef long int            int32_t;
300         typedef unsigned char       uint8_t;
301         typedef unsigned short int  uint16_t;
302         typedef unsigned long int   uint32_t;
303         /* \} */
304 #elif defined(__GNUC__) && defined(__AVR__)
305         /* avr-libc is weird... */
306         #include <inttypes.h>
307 #else
308         /* This is the correct location. */
309         #include <stdint.h>
310 #endif
311
312 /*!
313  * \name Types for hardware registers.
314  *
315  * Only use these types for registers whose contents can
316  * be changed asynchronously by external hardware.
317  *
318  * \{
319  */
320 #if CPU_DSP56K
321         /* Registers can be accessed only through 16-bit pointers */
322         typedef volatile uint16_t  reg16_t;
323 #else
324         typedef volatile uint8_t   reg8_t;
325         typedef volatile uint16_t  reg16_t;
326         typedef volatile uint32_t  reg32_t;
327 #endif
328 /*\}*/
329
330
331 /* Quasi-ANSI macros */
332 #ifndef offsetof
333         /*!
334          * Return the byte offset of the member \a m in struct \a s
335          *
336          * \note This macro should be defined in "stddef.h" and is sometimes
337          *       compiler-specific (g++ has a builtin for it).
338          */
339         #define offsetof(s,m)  (size_t)&(((s *)0)->m)
340 #endif
341 #ifndef countof
342         /*!
343          * Count the number of elements in the static array \a a
344          *
345          * \note This macro is non-standard, but implmenents a very common idiom
346          */
347         #define countof(a)  (sizeof(a) / sizeof(*(a)))
348 #endif
349
350 #endif /* DEVLIB_COMPILER_H */