summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/m68k/rtems/score/m68k.h
blob: c38a9a13ed4e146944cfb2c89813103c33b5a97f (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
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
/*  m68k.h
 *
 *  This include file contains information pertaining to the Motorola
 *  m68xxx processor family.
 *
 *  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 __M68k_h
#define __M68k_h

#ifdef __cplusplus
extern "C" {
#endif

/*
 *  This section contains the information required to build
 *  RTEMS for a particular member of the Motorola MC68xxx
 *  family.  It does this by setting variables to indicate
 *  which implementation dependent features are present in
 *  a particular member of the family.
 *
 *  Currently recognized:
 *     -m68000
 *     -m68000 -msoft-float
 *     -m68020
 *     -m68020 -msoft-float
 *     -m68030
 *     -m68040 -msoft-float
 *     -m68040
 *     -m68040 -msoft-float
 *     -m68060
 *     -m68060 -msoft-float
 *     -m68302        (no FP) (deprecated, use -m68000)
 *     -m68332        (no FP) (deprecated, use -mcpu32)
 *     -mcpu32        (no FP)
 *     -m5200         (no FP)
 *
 *  As of gcc 2.8.1 and egcs 1.1, there is no distinction made between
 *  the CPU32 and CPU32+.  The option -mcpu32 generates code which can
 *  be run on either core.  RTEMS distinguishes between these two cores
 *  because they have different alignment rules which impact performance.
 *  If you are using a CPU32+, then the symbol RTEMS__mcpu32p__ should
 *  be defined in your custom file (see make/custom/gen68360.cfg for an
 *  example of how to do this.  If gcc ever distinguishes between these
 *  two cores, then RTEMS__mcpu32p__ usage will be replaced with the
 *  appropriate compiler defined predefine.
 *
 *  Here is some information on the 040 variants (courtesy of Doug McBride,
 *  mcbride@rodin.colorado.edu):
 *
 *    "The 68040 is a superset of the 68EC040 and the 68LC040.  The
 *    68EC040 and 68LC040 do not have FPU's.  The 68LC040 and the
 *    68EC040 have renamed the DLE pin as JS0 which must be tied to
 *    Gnd or Vcc. The 68EC040 has renamed the MDIS pin as JS1.  The
 *    68EC040 has access control units instead of memory management units.
 *    The 68EC040 should not have the PFLUSH or PTEST instructions executed
 *    (cause an indeterminate result).  The 68EC040 and 68LC040 do not
 *    implement the DLE or multiplexed bus modes.  The 68EC040 does not
 *    implement the output buffer impedance selection mode of operation."
 *
 *  M68K_HAS_EXTB_L is used to enable/disable usage of the extb.l instruction
 *  which is not available for 68000 or 68ec000 cores (68000, 68001, 68008, 
 *  68010, 68302, 68306, 68307).  This instruction is available on the 68020
 *  up and the cpu32 based models.  
 *
 *  M68K_HAS_MISALIGNED is non-zero if the CPU allows byte-misaligned
 *  data access (68020, 68030, 68040, 68060, CPU32+).
 *
 *  NOTE:
 *    Eventually it would be nice to evaluate doing a lot of this section
 *    by having each model specify which core it uses and then go from there.
 */

/*
 *  Figure out all CPU Model Feature Flags based upon compiler 
 *  predefines.   Notice the only exception to this is that 
 *  gcc does not distinguish between CPU32 and CPU32+.  This
 *  feature selection logic is setup such that if RTEMS__mcpu32p__
 *  is defined, then CPU32+ rules are used.  Otherwise, the safe
 *  but less efficient CPU32 rules are used for the CPU32+.
 */

#if defined(__mc68020__)
 
#define CPU_MODEL_NAME          "m68020"
#define M68K_HAS_VBR             1
#define M68K_HAS_SEPARATE_STACKS 1
#define M68K_HAS_BFFFO           1
#define M68K_HAS_PREINDEXING     1
#define M68K_HAS_EXTB_L          1
#define M68K_HAS_MISALIGNED      1
# if defined (__HAVE_68881__)
# define M68K_HAS_FPU            1
# define M68K_HAS_FPSP_PACKAGE   0
# else
# define M68K_HAS_FPU            0
# define M68K_HAS_FPSP_PACKAGE   0
# endif
 
#elif defined(__mc68030__)
 
#define CPU_MODEL_NAME          "m68030"
#define M68K_HAS_VBR             1
#define M68K_HAS_SEPARATE_STACKS 1
#define M68K_HAS_BFFFO           1
#define M68K_HAS_PREINDEXING     1
#define M68K_HAS_EXTB_L          1
#define M68K_HAS_MISALIGNED      1
# if defined (__HAVE_68881__)
# define M68K_HAS_FPU            1
# define M68K_HAS_FPSP_PACKAGE   0
# else
# define M68K_HAS_FPU            0
# define M68K_HAS_FPSP_PACKAGE   0
# endif
 
#elif defined(__mc68040__)

#define CPU_MODEL_NAME          "m68040"
#define M68K_HAS_VBR             1
#define M68K_HAS_SEPARATE_STACKS 1
#define M68K_HAS_BFFFO           1
#define M68K_HAS_PREINDEXING     1
#define M68K_HAS_EXTB_L          1
#define M68K_HAS_MISALIGNED      1
# if defined (__HAVE_68881__)
# define M68K_HAS_FPU            1
# define M68K_HAS_FPSP_PACKAGE   1
# else
# define M68K_HAS_FPU            0
# define M68K_HAS_FPSP_PACKAGE   0
# endif
 
#elif defined(__mc68060__)

#define CPU_MODEL_NAME          "m68060"
#define M68K_HAS_VBR             1
#define M68K_HAS_SEPARATE_STACKS 0
#define M68K_HAS_BFFFO           1
#define M68K_HAS_PREINDEXING     1
#define M68K_HAS_EXTB_L          1
#define M68K_HAS_MISALIGNED      1
# if defined (__HAVE_68881__)
# define M68K_HAS_FPU            1
# define M68K_HAS_FPSP_PACKAGE   1
# else
# define M68K_HAS_FPU            0
# define M68K_HAS_FPSP_PACKAGE   0
# endif
 
#elif defined(__mc68302__)

#define CPU_MODEL_NAME          "m68302"
#define M68K_HAS_VBR             0
#define M68K_HAS_SEPARATE_STACKS 0
#define M68K_HAS_BFFFO           0
#define M68K_HAS_PREINDEXING     0
#define M68K_HAS_EXTB_L          0
#define M68K_HAS_MISALIGNED      0
#define M68K_HAS_FPU             0
#define M68K_HAS_FPSP_PACKAGE    0

  /* gcc and egcs do not distinguish between CPU32 and CPU32+ */
#elif defined(RTEMS__mcpu32p__)
 
#define CPU_MODEL_NAME          "mcpu32+"
#define M68K_HAS_VBR             1
#define M68K_HAS_SEPARATE_STACKS 0
#define M68K_HAS_BFFFO           0
#define M68K_HAS_PREINDEXING     1
#define M68K_HAS_EXTB_L          1
#define M68K_HAS_MISALIGNED      1
#define M68K_HAS_FPU             0
#define M68K_HAS_FPSP_PACKAGE    0

#elif defined(__mcpu32__)
 
#define CPU_MODEL_NAME          "mcpu32"
#define M68K_HAS_VBR             1
#define M68K_HAS_SEPARATE_STACKS 0
#define M68K_HAS_BFFFO           0
#define M68K_HAS_PREINDEXING     1
#define M68K_HAS_EXTB_L          1
#define M68K_HAS_MISALIGNED      0
#define M68K_HAS_FPU             0
#define M68K_HAS_FPSP_PACKAGE    0

#elif defined(__mcf5200__)
/* Motorola ColdFire V2 core - RISC/68020 hybrid */ 
#define CPU_MODEL_NAME         "m5200"
#define M68K_HAS_VBR             1
#define M68K_HAS_BFFFO           0
#define M68K_HAS_SEPARATE_STACKS 0
#define M68K_HAS_PREINDEXING     0
#define M68K_HAS_EXTB_L          1
#define M68K_HAS_MISALIGNED      1
#define M68K_HAS_FPU             0
#define M68K_HAS_FPSP_PACKAGE    0
#define M68K_COLDFIRE_ARCH       1

#elif defined(__mc68000__)
 
#define CPU_MODEL_NAME          "m68000"
#define M68K_HAS_VBR             0
#define M68K_HAS_SEPARATE_STACKS 0
#define M68K_HAS_BFFFO           0
#define M68K_HAS_PREINDEXING     0
#define M68K_HAS_EXTB_L          0
#define M68K_HAS_MISALIGNED      0
# if defined (__HAVE_68881__)
# define M68K_HAS_FPU            1
# define M68K_HAS_FPSP_PACKAGE   0
# else
# define M68K_HAS_FPU            0
# define M68K_HAS_FPSP_PACKAGE   0
# endif

#else

#error "Unsupported CPU model -- are you sure you're running a 68k compiler?"

#endif

/*
 *  If the above did not specify a ColdFire architecture, then set
 *  this flag to indicate that it is not a ColdFire CPU.
 */

#if !defined(M68K_COLDFIRE_ARCH)
#define M68K_COLDFIRE_ARCH       0
#endif

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

#if ( M68K_COLDFIRE_ARCH == 1 )
  #define CPU_NAME "Motorola ColdFire"
#else
  #define CPU_NAME "Motorola MC68xxx"
#endif

#ifndef ASM

#if ( M68K_COLDFIRE_ARCH == 1 )
#define m68k_disable_interrupts( _level ) \
   do { register unsigned32 _tmpsr = 0x0700; \
        asm volatile ( "move.w %%sr,%0\n\t" \
 		       "or.l   %0,%1\n\t" \
 		       "move.w %1,%%sr" \
 		       : "=d" (_level), "=d"(_tmpsr) : "1"(_tmpsr) ); \
   } while( 0 )
#else
#define m68k_disable_interrupts( _level ) \
  asm volatile ( "move.w  %%sr,%0\n\t" \
                 "or.w    #0x0700,%%sr" \
                    : "=d" (_level))
#endif

#define m68k_enable_interrupts( _level ) \
  asm volatile ( "move.w  %0,%%sr " : : "d" (_level));

#if ( M68K_COLDFIRE_ARCH == 1 )
#define m68k_flash_interrupts( _level ) \
   do { register unsigned32 _tmpsr = 0x0700; \
	asm volatile ( "move.w %2,%%sr\n\t" \
		       "or.l   %2,%1\n\t" \
		       "move.w %1,%%sr" \
		       : "=d"(_tmpsr) : "0"(_tmpsr), "d"(_level) ); \
   } while( 0 )
#else
#define m68k_flash_interrupts( _level ) \
  asm volatile ( "move.w  %0,%%sr\n\t" \
                 "or.w    #0x0700,%%sr" \
                    : : "d" (_level))
#endif

#define m68k_get_interrupt_level( _level ) \
  do { \
    register unsigned32 _tmpsr; \
    \
    asm volatile( "move.w %%sr,%0" : "=d" (_tmpsr)); \
    _level = (_tmpsr & 0x0700) >> 8; \
  } while (0)
    
#define m68k_set_interrupt_level( _newlevel ) \
  do { \
    register unsigned32 _tmpsr; \
    \
    asm volatile( "move.w  %%sr,%0" : "=d" (_tmpsr)); \
    _tmpsr = (_tmpsr & 0xf8ff) | ((_newlevel) << 8); \
    asm volatile( "move.w  %0,%%sr" : : "d" (_tmpsr)); \
  } while (0)

#if ( M68K_HAS_VBR == 1 && M68K_COLDFIRE_ARCH == 0 )
#define m68k_get_vbr( vbr ) \
  asm volatile ( "movec   %%vbr,%0 " : "=r" (vbr))

#define m68k_set_vbr( vbr ) \
  asm volatile ( "movec   %0,%%vbr " : : "r" (vbr))

#elif ( M68K_COLDFIRE_ARCH == 1 )
#define m68k_get_vbr( _vbr ) _vbr = (void *)_VBR

#define m68k_set_vbr( _vbr ) \
    asm volatile ("move.l  %%a7,%%d1 \n\t" \
	          "move.l  %0,%%a7\n\t"    \
	          "movec   %%a7,%%vbr\n\t" \
                  "move.l  %%d1,%%a7\n\t"  \
		  : : "d" (_vbr) : "d1" );
  
#else
#define m68k_get_vbr( _vbr ) _vbr = (void *)_VBR
#define m68k_set_vbr( _vbr )
#endif

/*
 *  The following routine swaps the endian format of an unsigned int.
 *  It must be static because it is referenced indirectly.
 */

static inline unsigned int m68k_swap_u32(
  unsigned int value
)
{
  unsigned int swapped = value;

  asm volatile( "rorw  #8,%0" : "=d" (swapped) : "0" (swapped) );
  asm volatile( "swap  %0"    : "=d" (swapped) : "0" (swapped) );
  asm volatile( "rorw  #8,%0" : "=d" (swapped) : "0" (swapped) );

  return( swapped );
}

static inline unsigned int m68k_swap_u16(
  unsigned int value
)
{
  unsigned short swapped = value;

  asm volatile( "rorw  #8,%0" : "=d" (swapped) : "0" (swapped) );

  return( swapped );
}

#define CPU_swap_u32( value )  m68k_swap_u32( value )
#define CPU_swap_u16( value )  m68k_swap_u16( value )


/*
 *  _CPU_virtual_to_physical
 *
 *  DESCRIPTION:
 *
 *	This function is used to map virtual addresses to physical
 *	addresses.
 * 
 *	FIXME: ASSUMES THAT VIRTUAL ADDRESSES ARE THE SAME AS THE
 *	PHYSICAL ADDRESSES
 */
static inline void * _CPU_virtual_to_physical (
  const void * d_addr )
{
  return (void *) d_addr;
}


/*  
 *  Since the cacr is common to all mc680x0, provide macros
 *  for masking values in that register.
 */

/* 
 *  Used to clear bits in the cacr.
 */
#define _CPU_CACR_AND(mask)                                        \
  {                                                                \
  register unsigned long _value = mask;                            \
  register unsigned long _ctl = 0;                                 \
  asm volatile ( "movec %%cacr, %0;           /* read the cacr */  \
                  andl %2, %0;                /* and with _val */  \
                  movec %1, %%cacr"           /* write the cacr */ \
   : "=d" (_ctl) : "0" (_ctl), "d" (_value) : "%%cc" );            \
  }


/*  
 *  Used to set bits in the cacr.
 */
#define _CPU_CACR_OR(mask)                                         \
	{                                                                \
  register unsigned long _value = mask;                            \
  register unsigned long _ctl = 0;                                 \
  asm volatile ( "movec %%cacr, %0;           /* read the cacr */  \
                  orl %2, %0;                 /* or with _val */   \
                  movec %1, %%cacr"           /* write the cacr */ \
   : "=d" (_ctl) : "0" (_ctl), "d" (_value) : "%%cc" );            \
  }

   
/*
 * CACHE MANAGER: The following functions are CPU-specific.
 * They provide the basic implementation for the rtems_* cache
 * management routines. If a given function has no meaning for the CPU,
 * it does nothing by default.
 */
#if ( defined(__mc68020__) || defined(__mc68030__) )
#define M68K_INST_CACHE_ALIGNMENT 16

#if defined(__mc68030__)
#define M68K_DATA_CACHE_ALIGNMENT 16

/* Only the mc68030 has a data cache; it is writethrough only. */

static inline void _CPU_flush_1_data_cache_line ( const void * d_addr ) {}
static inline void _CPU_flush_entire_data_cache ( const void * d_addr ) {}

static inline void _CPU_invalidate_1_data_cache_line (
  const void * d_addr )
{
  void * p_address = (void *) _CPU_virtual_to_physical( d_addr );
  asm volatile ( "movec %0, %%caar" :: "a" (p_address) );      /* write caar */
  _CPU_CACR_OR(0x00000400);
}

static inline void _CPU_invalidate_entire_data_cache (
	void )
{
  _CPU_CACR_OR( 0x00000800 );
}

static inline void _CPU_freeze_data_cache (
	void )
{
  _CPU_CACR_OR( 0x00000200 );
}

static inline void _CPU_unfreeze_data_cache (
	void )
{
  _CPU_CACR_AND( 0xFFFFFDFF );
}

static inline void _CPU_enable_data_cache (	void )
{
  _CPU_CACR_OR( 0x00000100 );
}
static inline void _CPU_disable_data_cache (	void )
{
  _CPU_CACR_AND( 0xFFFFFEFF );
}
#endif


/* Both the 68020 and 68030 have instruction caches */

static inline void _CPU_invalidate_1_inst_cache_line (
  const void * d_addr )
{
  void * p_address = (void *) _CPU_virtual_to_physical( d_addr );
  asm volatile ( "movec %0, %%caar" :: "a" (p_address) );      /* write caar */
  _CPU_CACR_OR( 0x00000004 );
}

static inline void _CPU_invalidate_entire_inst_cache (
	void )
{
  _CPU_CACR_OR( 0x00000008 );
}

static inline void _CPU_freeze_inst_cache (
	void )
{
  _CPU_CACR_OR( 0x00000002);
}

static inline void _CPU_unfreeze_inst_cache (
	void )
{
  _CPU_CACR_AND( 0xFFFFFFFD );
}

static inline void _CPU_enable_inst_cache (	void )
{
  _CPU_CACR_OR( 0x00000001 );
}

static inline void _CPU_disable_inst_cache (	void )
{
  _CPU_CACR_AND( 0xFFFFFFFE );
}


#elif ( defined(__mc68040__) || defined (__mc68060__) )

#define M68K_INST_CACHE_ALIGNMENT 16
#define M68K_DATA_CACHE_ALIGNMENT 16

/* Cannot be frozen */
static inline void _CPU_freeze_data_cache ( void ) {}
static inline void _CPU_unfreeze_data_cache ( void ) {}
static inline void _CPU_freeze_inst_cache ( void ) {}
static inline void _CPU_unfreeze_inst_cache ( void ) {}

static inline void _CPU_flush_1_data_cache_line (
  const void * d_addr )
{
  void * p_address = (void *) _CPU_virtual_to_physical( d_addr );
  asm volatile ( "cpushl %%dc,(%0)" :: "a" (p_address) );
}

static inline void _CPU_invalidate_1_data_cache_line (
  const void * d_addr )
{
  void * p_address = (void *) _CPU_virtual_to_physical( d_addr );
  asm volatile ( "cinvl %%dc,(%0)" :: "a" (p_address) );
}

static inline void _CPU_flush_entire_data_cache (
	void )
{
	asm volatile ( "cpusha %%dc" :: );
}

static inline void _CPU_invalidate_entire_data_cache (
	void )
{
	asm volatile ( "cinva %%dc" :: );
}

static inline void _CPU_enable_data_cache (
	void )
{
  _CPU_CACR_OR( 0x80000000 );
}

static inline void _CPU_disable_data_cache (
	void )
{
  _CPU_CACR_AND( 0x7FFFFFFF );
}

static inline void _CPU_invalidate_1_inst_cache_line (
  const void * i_addr )
{
  void * p_address = (void *)  _CPU_virtual_to_physical( i_addr );
  asm volatile ( "cinvl %%ic,(%0)" :: "a" (p_address) );
}

static inline void _CPU_invalidate_entire_inst_cache (
	void )
{
		asm volatile ( "cinva %%ic" :: );
}

static inline void _CPU_enable_inst_cache (
	void )
{
  _CPU_CACR_OR( 0x00008000 );
}

static inline void _CPU_disable_inst_cache (
	void )
{
	_CPU_CACR_AND( 0xFFFF7FFF );
}
#endif


#if defined(M68K_DATA_CACHE_ALIGNMENT)
#define _CPU_DATA_CACHE_ALIGNMENT M68K_DATA_CACHE_ALIGNMENT
#endif

#if defined(M68K_INST_CACHE_ALIGNMENT)
#define _CPU_INST_CACHE_ALIGNMENT M68K_INST_CACHE_ALIGNMENT
#endif


#endif  /* !ASM */

#ifdef __cplusplus
}
#endif

#endif /* __M68K_h */
/* end of include file */