summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/c4x/rtems/score/c4x.h
blob: d3ef758693e91615d7032d7a799d9e5a988121e4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
/*  c4x.h
 *
 *  This file is an example (i.e. "no CPU") of the file which is
 *  created for each CPU family port of RTEMS.
 *
 *
 *  COPYRIGHT (c) 1989-1999.
 *  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.OARcorp.com/rtems/license.html.
 *
 *  $Id$
 *
 */

#ifndef _INCLUDE_C4X_h
#define _INCLUDE_C4X_h

#ifdef __cplusplus
extern "C" {
#endif

/*
 *  This file contains the information required to build
 *  RTEMS for a particular member of the "no cpu"
 *  family when executing in protected mode.  It does
 *  this by setting variables to indicate which implementation
 *  dependent features are present in a particular member
 *  of the family.
 */
 
#if defined(c30)
#define CPU_MODEL_NAME  "C30"

#elif defined(c31)
#define CPU_MODEL_NAME  "C31"
 
#elif defined(c32)
#define CPU_MODEL_NAME  "C32"
 
#elif defined(c40)
#define CPU_MODEL_NAME  "C40"
 
#elif defined(c44)
#define CPU_MODEL_NAME  "C44"
 
#else
 
#error "Unsupported CPU Model"
 
#endif

/*
 *  Define the name of the CPU family.
 */

#define CPU_NAME "Texas Instruments C3x/C4x"

/*
 *  This port is a little unusual in that even though there are "floating
 *  point registers", the notion of floating point is very inherent to
 *  applications.  In addition, the calling conventions require that
 *  only a few extended registers be preserved across subroutine calls.
 *  The overhead of including these few registers in the basic 
 *  context is small compared to the overhead of managing the notion
 *  of separate floating point contexts.  So we decided to pretend that
 *  there is no FPU on the C3x or C4x.
 */

#define C4X_HAS_FPU  0

/*
 *  Routines to manipulate the bits in the Status Word (ST).
 */

#define C4X_ST_C      0x0001
#define C4X_ST_V      0x0002
#define C4X_ST_Z      0x0004
#define C4X_ST_N      0x0008
#define C4X_ST_UF     0x0010
#define C4X_ST_LV     0x0020
#define C4X_ST_LUF    0x0040
#define C4X_ST_OVM    0x0080
#define C4X_ST_RM     0x0100
#define C4X_ST_CF     0x0400
#define C4X_ST_CE     0x0800
#define C4X_ST_CC     0x1000
#define C4X_ST_GIE    0x2000

#ifndef _TMS320C40
#define C3X_IE_INTERRUPT_MASK_BITS     0xffff
#define C3x_IE_INTERRUPTS_ALL_ENABLED  0x0000
#define C3x_IE_INTERRUPTS_ALL_DISABLED 0xffff
#endif

#ifndef ASM

/*
 *  A nop macro.
 */

#define c4x_nop() \
  __asm__("nop");

/*
 *  Routines to set and clear individual bits in the ST (status word).
 *
 *  cpu_st_bit_clear  - clear bit in ST
 *  cpu_st_bit_set    - set bit in ST
 *  cpu_st_get        - obtain entire ST
 */

#ifdef _TMS320C40
#define c4x_gie_nop()
#else
#define c4x_gie_nop() { c4x_nop(); c4x_nop(); }
#endif

#define cpu_st_bit_clear(_st_bit) \
  do { \
    __asm__("andn %0,st" : : "g" (_st_bit) : "cc"); \
    c4x_gie_nop(); \
  } while (0)

#define cpu_st_bit_set(_st_bit) \
  do { \
    __asm__("or %0,st" : : "g" (_st_bit) : "cc"); \
    c4x_gie_nop(); \
  } while (0)

static inline unsigned int cpu_st_get(void)
{
  register unsigned int st_value;
  __asm__("ldi st, %0" : "=r" (st_value));
  return st_value;
}

/*
 *  Routines to manipulate the Global Interrupt Enable (GIE) bit in
 *  the Status Word (ST).
 *
 *  c4x_global_interrupts_get      - returns current GIE setting
 *  c4x_global_interrupts_disable  - disables global interrupts
 *  c4x_global_interrupts_enable   - enables global interrupts
 *  c4x_global_interrupts_restore  - restores GIE to pre-disable state
 *  c4x_global_interrupts_flash    - temporarily enable global interrupts
 */

#define c4x_global_interrupts_get() \
  (cpu_st_get() & C4X_ST_GIE)
  
#define c4x_global_interrupts_disable() \
  cpu_st_bit_clear(C4X_ST_GIE)

#define c4x_global_interrupts_enable() \
  cpu_st_bit_set(C4X_ST_GIE)

#define c4x_global_interrupts_restore(_old_level) \
  cpu_st_bit_set(_old_level)

#define c4x_global_interrupts_flash(_old_level) \
  do { \
    cpu_st_bit_set(_old_level); \
    cpu_st_bit_clear(C4X_ST_GIE); \
  } while (0)

#ifndef _TMS320C40

/*
 *  Routines to set and get the IF register
 *
 *  c3x_get_if     - obtains IF register
 *  c3x_set_if     - sets IF register
 */

static inline unsigned int c3x_get_if(void)
{
  register unsigned int _if_value;

  __asm__( "ldi if, %0" : "=r" (_if_value) );
  return _if_value;
}

static inline void c3x_set_if(unsigned int _if_value)
{
  __asm__( "ldi %0, if" : : "g" (_if_value) : "if", "cc"); 
}

/*
 *  Routines to set and get the IE register
 *
 *  c3x_get_ie     - obtains IE register
 *  c3x_set_ie     - sets IE register
 */

static inline unsigned int c3x_get_ie(void)
{
  register unsigned int _ie_value;

  __asm__ volatile ( "ldi ie, %0" : "=r" (_ie_value) );
  return _ie_value;
}

static inline void c3x_set_ie(unsigned int _ie_value)
{
  __asm__ volatile ( "ldi %0, ie" : : "g" (_ie_value) : "ie", "cc"); 
}

/*
 *  Routines to manipulates the mask portion of the IE register.
 *
 *  c3x_ie_mask_all     - returns previous IE mask
 *  c3x_ie_mask_restore - restores previous IE mask
 *  c3x_ie_mask_flash   - temporarily restores previous IE mask
 *  c3x_ie_mask_set     - sets a specific set of the IE mask
 */
 
#define c3x_ie_mask_all( _isr_cookie ) \
  do { \
    __asm__("ldi  ie,%0\n" \
            "\tandn 0ffffh, ie" \
          : "=r" (_isr_cookie): : "ie", "cc" ); \
  } while (0)

#define c3x_ie_mask_restore( _isr_cookie )  \
  do { \
    __asm__("or %0, ie" \
          : : "g" (_isr_cookie) : "ie", "cc" ); \
  } while (0)

#define c3x_ie_mask_flash( _isr_cookie ) \
  do { \
    __asm__("or %0, ie\n" \
           "\tandn 0ffffh, ie" \
          : : "g" (_isr_cookie) : "ie", "cc" ); \
  } while (0)

#define c3x_ie_mask_set( _new_mask ) \
  do { unsigned int _ie_mask; \
    unsigned int _ie_value; \
    \
    if ( _new_mask == 0 ) _ie_mask = 0; \
    else                  _ie_mask = 0xffff; \
    _ie_value = c3x_get_ie(); \
    _ie_value &= C4X_IE_INTERRUPT_MASK_BITS; \
    _ie_value |= _ie_mask; \
    c3x_set_ie(_ie_value); \
  } while (0)
#endif
/* end of C3x specific interrupt flag routines */

/*
 *  This is a section of C4x specific interrupt flag management routines.
 */

#ifdef _TMS320C40

/*
 *  Routines to set and get the IIF register
 *
 *  c4x_get_iif     - obtains IIF register
 *  c4x_set_iif     - sets IIF register
 */

static inline unsigned int c4x_get_iif(void)
{
  register unsigned int _iif_value;

  __asm__( "ldi iif, %0" : "=r" (_iif_value) );
  return _iif_value;
}

static inline void c4x_set_iif(unsigned int _iif_value)
{
  __asm__( "ldi %0, iif" : : "g" (_iif_value) : "iif", "cc"); 
}

/*
 *  Routines to set and get the IIE register
 *
 *  c4x_get_iie     - obtains IIE register
 *  c4x_set_iie     - sets IIE register
 */

static inline unsigned int c4x_get_iie(void)
{
  register unsigned int _iie_value;

  __asm__( "ldi iie, %0" : "=r" (_iie_value) );
  return _iie_value;
}

static inline void c4x_set_iie(unsigned int _iie_value)
{
  __asm__( "ldi %0, iie" : : "g" (_iie_value) : "iie", "cc"); 
}

/*
 *  Routines to manipulates the mask portion of the IIE register.
 *
 *  c4x_ie_mask_all     - returns previous IIE mask
 *  c4x_ie_mask_restore - restores previous IIE mask
 *  c4x_ie_mask_flash   - temporarily restores previous IIE mask
 *  c4x_ie_mask_set     - sets a specific set of the IIE mask
 */

#if 0
#warning "C4x IIE masking routines not implemented."
#define c4x_iie_mask_all( _isr_cookie )
#define c4x_iie_mask_restore( _isr_cookie )
#define c4x_iie_mask_flash( _isr_cookie )
#define c4x_iie_mask_set( _new_mask )
#endif

#endif
/* end of C4x specific interrupt flag routines */

/*
 *  Routines to access the Interrupt Trap Table Pointer
 *
 *  c4x_get_ittp    - get ITTP
 *  c4x_set_ittp    - set ITTP
 */

static inline void * c4x_get_ittp(void)
{ 
  register unsigned int _if_value;
  
  __asm__( "ldi if, %0" : "=r" (_if_value) );
  return (void *)((_if_value & 0xffff0000) >> 8); 
}  

static inline void c4x_set_ittp(void *_ittp_value)
{  
  unsigned int _if_value;
  unsigned int _ittp_field;

#ifdef _TMS320C40
  _if_value = c4x_get_iif();
#else
  _if_value = c3x_get_if();
#endif
  _if_value &= 0xffff;
  _ittp_field = (((unsigned int) _ittp_value) >> 8);
  _if_value |= _ittp_field << 16 ;
#ifdef _TMS320C40
  c4x_set_iif( _if_value );
#else
  c3x_set_if( _if_value );
#endif
}  

#endif /* ifndef ASM */

#ifdef __cplusplus
}
#endif

#endif /* ! _INCLUDE_C4X_h */
/* end of include file */