Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:24

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  *  @file
0005  *
0006  *  @brief Motorola MC68xxx Dependent Source
0007  */
0008 
0009 /*
0010  *  COPYRIGHT (c) 1989-1999.
0011  *  On-Line Applications Research Corporation (OAR).
0012  *
0013  * Redistribution and use in source and binary forms, with or without
0014  * modification, are permitted provided that the following conditions
0015  * are met:
0016  * 1. Redistributions of source code must retain the above copyright
0017  *    notice, this list of conditions and the following disclaimer.
0018  * 2. Redistributions in binary form must reproduce the above copyright
0019  *    notice, this list of conditions and the following disclaimer in the
0020  *    documentation and/or other materials provided with the distribution.
0021  *
0022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0023  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0025  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0026  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0027  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0028  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0029  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0030  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0031  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0032  * POSSIBILITY OF SUCH DAMAGE.
0033  */
0034 
0035 #ifdef HAVE_CONFIG_H
0036 #include "config.h"
0037 #endif
0038 
0039 #include <rtems/score/cpuimpl.h>
0040 #include <rtems/score/isr.h>
0041 #include <rtems/score/percpu.h>
0042 #include <rtems/score/tls.h>
0043 #include <rtems/config.h>
0044 
0045 #if ( M68K_HAS_VBR == 0 )
0046 
0047 /*
0048  * Table of ISR handler entries that resides in RAM. The FORMAT/ID is
0049  * pushed onto the stack. This is not is the same order as VBR processors.
0050  * The ISR handler takes the format and uses it for dispatching the user
0051  * handler.
0052  */
0053 
0054 typedef struct {
0055   uint16_t   move_a7;            /* move #FORMAT_ID,%a7@- */
0056   uint16_t   format_id;
0057   uint16_t   jmp;                /* jmp  _ISR_Handlers */
0058   uint32_t   isr_handler;
0059 } _CPU_ISR_handler_entry;
0060 
0061 #define M68K_MOVE_A7 0x3F3C
0062 #define M68K_JMP     0x4EF9
0063 
0064 /* points to jsr-exception-table in targets wo/ VBR register */
0065 static _CPU_ISR_handler_entry
0066 _CPU_ISR_jump_table[ CPU_INTERRUPT_NUMBER_OF_VECTORS ];
0067 
0068 #endif /* M68K_HAS_VBR */
0069 
0070 #if (M68K_HAS_FPSP_PACKAGE == 1)
0071 int (*_FPSP_install_raw_handler)(
0072   uint32_t   vector,
0073   CPU_ISR_raw_handler new_handler,
0074   CPU_ISR_raw_handler *old_handler
0075 );
0076 #endif
0077 
0078 #if defined( __mcoldfire__ ) && ( M68K_HAS_FPU == 1 )
0079   uint32_t _CPU_cacr_shadow;
0080 #endif
0081 
0082 static void m68k_install_interrupt_stack( void )
0083 {
0084 #if ( M68K_HAS_SEPARATE_STACKS == 1 )
0085   uintptr_t isp = (uintptr_t) _ISR_Stack_area_end;
0086 
0087   __asm__ volatile ( "movec %0,%%isp" : "=r" (isp) : "0" (isp) );
0088 #endif
0089 }
0090 
0091 void _CPU_Initialize(void)
0092 {
0093 #if ( M68K_HAS_VBR == 0 )
0094   /* fill the isr redirect table with the code to place the format/id
0095      onto the stack */
0096 
0097   uint32_t   slot;
0098 
0099   for (slot = 0; slot < CPU_INTERRUPT_NUMBER_OF_VECTORS; slot++)
0100   {
0101     _CPU_ISR_jump_table[slot].move_a7 = M68K_MOVE_A7;
0102     _CPU_ISR_jump_table[slot].format_id = slot << 2;
0103     _CPU_ISR_jump_table[slot].jmp = M68K_JMP;
0104     _CPU_ISR_jump_table[slot].isr_handler = (uint32_t) 0xDEADDEAD;
0105   }
0106 #endif /* M68K_HAS_VBR */
0107 
0108   m68k_install_interrupt_stack();
0109 }
0110 
0111 uint32_t   _CPU_ISR_Get_level( void )
0112 {
0113   uint32_t   level;
0114 
0115   m68k_get_interrupt_level( level );
0116 
0117   return level;
0118 }
0119 
0120 void _CPU_ISR_install_raw_handler(
0121   uint32_t             vector,
0122   CPU_ISR_raw_handler  new_handler,
0123   CPU_ISR_raw_handler *old_handler
0124 )
0125 {
0126 #if ( M68K_HAS_VBR == 1 )
0127   CPU_ISR_raw_handler *interrupt_table = NULL;
0128 #else
0129   _CPU_ISR_handler_entry *interrupt_table = NULL;
0130 #endif
0131 
0132 #if (M68K_HAS_FPSP_PACKAGE == 1)
0133   /*
0134    *  If this vector being installed is one related to FP, then the
0135    *  FPSP will install the handler itself and handle it completely
0136    *  with no intervention from RTEMS.
0137    */
0138 
0139   if (*_FPSP_install_raw_handler &&
0140       (*_FPSP_install_raw_handler)(vector, new_handler, *old_handler))
0141         return;
0142 #endif
0143 
0144 
0145   /*
0146    *  On CPU models without a VBR, it is necessary for there to be some
0147    *  header code for each ISR which saves a register, loads the vector
0148    *  number, and jumps to _ISR_Handler.
0149    */
0150 
0151   m68k_get_vbr( interrupt_table );
0152 #if ( M68K_HAS_VBR == 1 )
0153   *old_handler = interrupt_table[ vector ];
0154   interrupt_table[ vector ] = new_handler;
0155 #else
0156 
0157   /*
0158    *  Install handler into RTEMS jump table and if VBR table is in
0159    *  RAM, install the pointer to the appropriate jump table slot.
0160    *  If the VBR table is in ROM, it is the BSP's responsibility to
0161    *  load it appropriately to vector to the RTEMS jump table.
0162    */
0163 
0164   *old_handler = (CPU_ISR_raw_handler) _CPU_ISR_jump_table[vector].isr_handler;
0165   _CPU_ISR_jump_table[vector].isr_handler = (uint32_t) new_handler;
0166   if ( (uint32_t) interrupt_table != 0xFFFFFFFF )
0167     interrupt_table[ vector ] = &_CPU_ISR_jump_table[vector];
0168 #endif /* M68K_HAS_VBR */
0169 }
0170 
0171 void _CPU_ISR_install_vector(
0172   uint32_t         vector,
0173   CPU_ISR_handler  new_handler,
0174   CPU_ISR_handler *old_handler
0175 )
0176 {
0177   CPU_ISR_raw_handler ignored = 0;  /* to avoid warning */
0178 
0179   *old_handler = _ISR_Vector_table[ vector ];
0180 
0181   _CPU_ISR_install_raw_handler( vector, _ISR_Handler, &ignored );
0182 
0183   _ISR_Vector_table[ vector ] = new_handler;
0184 }
0185 
0186 #if ( M68K_HAS_BFFFO != 1 )
0187 /*
0188  * Returns table for duplication of the BFFFO instruction (16 bits only)
0189  */
0190 const unsigned char _CPU_m68k_BFFFO_table[256] = {
0191     8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
0192     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
0193     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
0194     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
0195     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0196     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0197     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0198     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0199     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0200     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0201     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0202     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0203     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0204     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0205     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0206     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0207 };
0208 #endif
0209 
0210 /*
0211  *  The following code context switches the software FPU emulation
0212  *  code provided with GCC.
0213  */
0214 
0215 #if (CPU_SOFTWARE_FP == TRUE)
0216 extern Context_Control_fp _fpCCR;
0217 
0218 void _CPU_Context_save_fp (Context_Control_fp **fp_context_ptr)
0219 {
0220   Context_Control_fp *fp;
0221 
0222   fp = *fp_context_ptr;
0223 
0224   *fp = _fpCCR;
0225 }
0226 
0227 void _CPU_Context_restore_fp (Context_Control_fp **fp_context_ptr)
0228 {
0229   Context_Control_fp *fp;
0230 
0231   fp = *fp_context_ptr;
0232 
0233   _fpCCR = *fp;
0234 }
0235 #endif
0236 
0237 void _CPU_Context_Initialize(
0238   Context_Control *the_context,
0239   void *stack_area_begin,
0240   size_t stack_area_size,
0241   uint32_t new_level,
0242   void (*entry_point)( void ),
0243   bool is_fp,
0244   void *tls_area
0245 )
0246 {
0247   uint32_t stack;
0248 
0249   the_context->sr      = 0x3000 | (new_level << 8);
0250   stack                = (uint32_t)stack_area_begin + stack_area_size - 4;
0251   the_context->a7_msp  = (void *)stack;
0252   *(void **)stack      = (void *)entry_point;
0253 
0254 #if (defined(__mcoldfire__) && ( M68K_HAS_FPU == 1 ))
0255   the_context->fpu_dis = is_fp ? 0x00 : 0x10;
0256 #endif
0257 
0258   if ( tls_area != NULL ) {
0259     the_context->thread_pointer =
0260       (char *) _TLS_Initialize_area( tls_area ) + 0x7000;
0261   } else {
0262     the_context->thread_pointer = NULL;
0263   }
0264 }