Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  cpu_asm.s
0004  *
0005  *  This file contains all assembly code for the MC68020 implementation
0006  *  of RTEMS.
0007  *
0008  *  COPYRIGHT (c) 1989-2008.
0009  *  On-Line Applications Research Corporation (OAR).
0010  *
0011  * Redistribution and use in source and binary forms, with or without
0012  * modification, are permitted provided that the following conditions
0013  * are met:
0014  * 1. Redistributions of source code must retain the above copyright
0015  *    notice, this list of conditions and the following disclaimer.
0016  * 2. Redistributions in binary form must reproduce the above copyright
0017  *    notice, this list of conditions and the following disclaimer in the
0018  *    documentation and/or other materials provided with the distribution.
0019  *
0020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0021  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0022  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0023  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0024  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0025  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0026  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0027  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0028  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0029  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0030  * POSSIBILITY OF SUCH DAMAGE.
0031  */
0032 
0033 
0034 #ifdef HAVE_CONFIG_H
0035 #include "config.h"
0036 #endif
0037 
0038 #include <rtems/asm.h>
0039 #include <rtems/score/percpu.h>
0040 
0041 /*  void _CPU_Context_switch( run_context, heir_context )
0042  *
0043  *  This routine performs a normal non-FP context.
0044  */
0045 
0046         .align  4
0047         .global SYM (_CPU_Context_switch)
0048 
0049 .set RUNCONTEXT_ARG,   4                 | save context argument
0050 .set HEIRCONTEXT_ARG,  8                 | restore context argument
0051 
0052 SYM (_CPU_Context_switch):
0053           moval    a7@(RUNCONTEXT_ARG),a0| a0 = running thread context
0054           movw     sr,d1                 | d1 = status register
0055           movml    d1-d7/a2-a7,a0@       | save context
0056 
0057           moval    a7@(HEIRCONTEXT_ARG),a0| a0 = heir thread context
0058 
0059 #if defined( __mcoldfire__ ) && ( M68K_HAS_FPU == 1 )
0060           moveb    a0@(13*4),d0                 | get context specific DF bit info in d0
0061           btstb    #4,d0                        | test context specific DF bit info
0062           beq      fpu_on                       | branch if FPU needs to be switched on
0063 
0064 fpu_off:  movl     _CPU_cacr_shadow,d0          | get content of _CPU_cacr_shadow in d0
0065           btstl    #4,d0                        | test DF bit info in d0
0066           bne      restore                      | branch if FPU is already switched off
0067           bsetl    #4,d0                        | set DF bit in d0
0068           bra      cacr_set                     | branch to set the new FPU setting in cacr and _CPU_cacr_shadow
0069 
0070 fpu_on:   movl     _CPU_cacr_shadow,d0          | get content of _CPU_cacr_shadow in d1
0071           btstl    #4,d0                        | test context specific DF bit info
0072           beq      restore                      | branch if FPU is already switched on
0073           bclrl    #4,d0                        | clear DF bit info in d0
0074 
0075 cacr_set: movew    sr,d1                        | get content of sr in d1
0076           oril     #0x00000700,d1               | mask d1
0077           movew    d1,sr                        | disable all interrupts
0078           movl     d0,_CPU_cacr_shadow          | move _CPU_cacr_shadow to d1
0079           movec    d0,cacr                      | enable FPU in cacr
0080 #endif
0081 
0082 
0083 restore:  movml    a0@,d1-d7/a2-a7       | restore context
0084           movw     d1,sr                 | restore status register
0085           rts
0086 
0087         .global SYM (_CPU_Context_Restart_self)
0088 .set    CONTEXT_ARG, 4                   | context arg
0089 
0090 #if defined( __mcoldfire__ ) && ( M68K_HAS_FPU == 1 )
0091 /* XXX _CPU_Context_switch maintains FPU context -- do we have to restore
0092  *     that, too??
0093  */
0094 #warning "_CPU_Context_Restart_self restoring FPU context not implemented"
0095 #endif
0096 SYM(_CPU_Context_Restart_self):
0097          moval    a7@(CONTEXT_ARG),a0
0098          bra      restore
0099 /*
0100  * Floating point context save and restore.
0101  *
0102  * The code for the MC68881 or MC68882 is based upon the code shown on pages
0103  * 6-38 of the MC68881/68882 Users Manual (rev 1).  CPU_FP_CONTEXT_SIZE is
0104  * higher than expected to account for the -1 pushed at end of this sequence.
0105  */
0106 
0107 #if ( CPU_HARDWARE_FP == TRUE )
0108 
0109 .set FPCONTEXT_ARG,   4                   | save FP context argument
0110 
0111         .align  4
0112         .global SYM (_CPU_Context_save_fp)
0113 SYM (_CPU_Context_save_fp):
0114 
0115         /* Get context save area pointer argument from the stack */
0116         moval    a7@(FPCONTEXT_ARG), a1
0117         moval    a1@, a0
0118 
0119   #if defined( __mcoldfire__ )
0120         /* Move MACSR to data register and disable rounding */
0121         movel    macsr, d0
0122         clrl     d1
0123         movl     d1, macsr
0124 
0125         /* Save MACSR and ACC0 */
0126         movl     acc0, d1
0127         moveml   d0-d1, a0@(0)
0128 
0129         /* Save ACC1 and ACC2 */
0130         movl     acc1, d0
0131         movl     acc2, d1
0132         moveml   d0-d1, a0@(8)
0133 
0134         /* Save ACC3 and ACCEXT01 */
0135         movl     acc3, d0
0136         movl     accext01, d1
0137         moveml   d0-d1, a0@(16)
0138 
0139         /* Save ACCEXT23 and MASK */
0140         movl     accext23, d0
0141         movl     mask, d1
0142         moveml   d0-d1, a0@(24)
0143 
0144     #if ( M68K_HAS_FPU == 1 )
0145         /* Save FP state */
0146         fsave    a0@(32)
0147 
0148         /* Save FP instruction address */
0149         fmovel   fpi, a0@(48)
0150 
0151         /* Save FP data */
0152         fmovem   fp0-fp7, a0@(52)
0153     #endif
0154   #else
0155     #if defined( __mc68060__ )
0156         lea      a0@(-M68K_FP_STATE_SIZE), a0
0157         fsave    a0@                      | save 68060 state frame
0158     #else
0159         fsave    a0@-                     | save 68881/68882 state frame
0160     #endif
0161         tstb     a0@                      | check for a null frame
0162         beq.b    nosv                     | Yes, skip save of user model
0163         fmovem   fp0-fp7, a0@-            | save data registers (fp0-fp7)
0164         fmovem   fpc/fps/fpi, a0@-        | and save control registers
0165         movl     #-1, a0@-                | place not-null flag on stack
0166 nosv:
0167         movl     a0, a1@                  | save pointer to saved context
0168   #endif
0169 
0170         /* Return */
0171         rts
0172 
0173         .align  4
0174         .global SYM (_CPU_Context_restore_fp)
0175 SYM (_CPU_Context_restore_fp):
0176 
0177         /* Get context save area pointer argument from the stack */
0178         moval    a7@(FPCONTEXT_ARG), a1
0179         moval    a1@, a0
0180 
0181   #if defined( __mcoldfire__ )
0182     #if ( M68K_HAS_FPU == 1 )
0183         /* Restore FP data */
0184         fmovem   a0@(52), fp0-fp7
0185 
0186         /* Restore FP instruction address */
0187         fmovel   a0@(48), fpi
0188 
0189         /* Restore FP state */
0190         frestore a0@(32)
0191     #endif
0192 
0193         /* Disable rounding */
0194         clrl     d0
0195         movl     d0, macsr
0196 
0197         /* Restore MASK and ACCEXT23 */
0198         moveml   a0@(24), d0-d1
0199         movl     d0, mask
0200         movl     d1, accext23
0201 
0202         /* Restore ACCEXT01 and ACC3 */
0203         moveml   a0@(16), d0-d1
0204         movl     d0, accext01
0205         movl     d1, acc3
0206 
0207         /* Restore ACC2 and ACC1 */
0208         moveml   a0@(8), d0-d1
0209         movl     d0, acc2
0210         movl     d1, acc1
0211 
0212         /* Restore ACC0 and MACSR */
0213         moveml   a0@(0), d0-d1
0214         movl     d0, acc0
0215         movl     d1, macsr
0216   #else
0217         tstb     a0@                      | Null context frame?
0218         beq.b    norst                    | Yes, skip fp restore
0219         addql    #4, a0                   | throwaway non-null flag
0220         fmovem   a0@+, fpc/fps/fpi        | restore control registers
0221         fmovem   a0@+, fp0-fp7            | restore data regs (fp0-fp7)
0222 norst:
0223     #if defined( __mc68060__ )
0224         frestore a0@                      | restore 68060 state frame
0225         lea      a0@(M68K_FP_STATE_SIZE), a0
0226     #else
0227         frestore a0@+                     | restore 68881/68882 state frame
0228     #endif
0229         movl     a0, a1@                  | save pointer to saved context
0230   #endif
0231 
0232         /* Return */
0233         rts
0234 #endif
0235 
0236 /*void _ISR_Handler()
0237  *
0238  *  This routine provides the RTEMS interrupt management.
0239  *
0240  *  NOTE:
0241  *    Upon entry, the master stack will contain an interrupt stack frame
0242  *    back to the interrupted thread and the interrupt stack will contain
0243  *    a throwaway interrupt stack frame.  If dispatching is enabled, and this
0244  *    is the outer most interrupt, and a context switch is necessary or
0245  *    the current thread has pending signals, then set up the master stack to
0246  *    transfer control to the interrupt dispatcher.
0247  */
0248 
0249 #if ( defined(__mcoldfire__) )
0250 .set SR_OFFSET,    2                     | Status register offset
0251 .set PC_OFFSET,    4                     | Program Counter offset
0252 .set FVO_OFFSET,   0                     | Format/vector offset
0253 #elif ( M68K_HAS_VBR == 1)
0254 .set SR_OFFSET,    0                     | Status register offset
0255 .set PC_OFFSET,    2                     | Program Counter offset
0256 .set FVO_OFFSET,   6                     | Format/vector offset
0257 #else
0258 .set SR_OFFSET,    2                     | Status register offset
0259 .set PC_OFFSET,    4                     | Program Counter offset
0260 .set FVO_OFFSET,   0                     | Format/vector offset placed in the stack
0261 #endif /* M68K_HAS_VBR */
0262 
0263 .set SAVED,        16                    | space for saved registers
0264 
0265         .align  4
0266         .global SYM (_ISR_Handler)
0267 
0268 SYM (_ISR_Handler):
0269                                          | disable multitasking
0270         addql   #1,THREAD_DISPATCH_DISABLE_LEVEL
0271 #if ( !defined(__mcoldfire__) )
0272         moveml  d0-d1/a0-a1,a7@-         | save d0-d1,a0-a1
0273 #else
0274         lea     a7@(-SAVED),a7
0275         movm.l  d0-d1/a0-a1,a7@          | save d0-d1,a0-a1
0276 #endif
0277         movew   a7@(SAVED+FVO_OFFSET),d0 | d0 = F/VO
0278         andl    #0x03fc,d0               | d0 = vector offset in vbr
0279 
0280 
0281 #if ( M68K_HAS_SEPARATE_STACKS == 0 )
0282         | Make a0 point just above interrupt stack
0283         movel   INTERRUPT_STACK_HIGH,a0
0284         cmpl    INTERRUPT_STACK_LOW,a7  | stack below interrupt stack?
0285         bcs.b   1f                      | yes, switch to interrupt stack
0286         cmpl    a0,a7                   | stack above interrupt stack?
0287         bcs.b   2f                      | no, do not switch stacks
0288 1:
0289         movel   a7,a1                   | copy task stack pointer
0290         movel   a0,a7                   | switch to interrupt stack
0291         movel   a1,a7@-                 | store task stack pointer
0292                                         |     on interrupt stack
0293 2:
0294 #endif /* M68K_HAS_SEPARATE_STACKS == 0 */
0295 
0296         addql   #1,ISR_NEST_LEVEL        | one nest level deeper
0297 
0298         lea     SYM(_ISR_Vector_table),a0
0299         movel   (a0,d0),a0               | a0 = address of user routine
0300 
0301         lsrl    #2,d0                    | d0 = vector number
0302         movel   d0,a7@-                  | push vector number
0303         jbsr    a0@                      | invoke the user ISR
0304         addql   #4,a7                    | remove vector number
0305         subql   #1,ISR_NEST_LEVEL        | Reduce interrupt-nesting count
0306 
0307 #if ( M68K_HAS_SEPARATE_STACKS == 0 )
0308         movel   INTERRUPT_STACK_HIGH,a0
0309         subql   #4,a0
0310         cmpl    a0,a7                   | At top of interrupt stack?
0311         bne.b   1f                      | No, do not restore task stack pointer
0312         movel   (a7),a7                 | Restore task stack pointer
0313 1:
0314 #endif /* M68K_HAS_SEPARATE_STACKS == 0 */
0315         subql   #1,THREAD_DISPATCH_DISABLE_LEVEL
0316                                          | unnest multitasking
0317         bne.b    exit                    | If dispatch disabled, exit
0318 
0319 #if ( M68K_HAS_SEPARATE_STACKS == 1 )
0320         movew   #0xf000,d0               | isolate format nibble
0321         andw    a7@(SAVED+FVO_OFFSET),d0 | get F/VO
0322         cmpiw   #0x1000,d0               | is it a throwaway isf?
0323         bne.b   exit                     | NOT outer level, so branch
0324 #else
0325 /*
0326  * If we have a CPU which allows a higher-priority interrupt to preempt a
0327  * lower priority handler before the lower-priority handler can increment
0328  * _Thread_Dispatch_disable_level then we must check the PC on the stack to
0329  * see if it is _ISR_Handler.  If it is we have the case of nesting interrupts
0330  * without the dispatch level being incremented.
0331  */
0332   #if ( !defined(__mcoldfire__) && !__mc68060__ )
0333         cmpl    #_ISR_Handler,a7@(SAVED+PC_OFFSET)
0334         beq.b   exit
0335   #endif
0336 #endif
0337         tstb    DISPATCH_NEEDED
0338                                          | Is thread switch necessary?
0339         beq.b   exit                     | No, then exit
0340 
0341 bframe: 
0342                                          | If sent, will be processed
0343 #if ( M68K_HAS_SEPARATE_STACKS == 1 )
0344         movec   msp,a0                   | a0 = master stack pointer
0345         movew   #0,a0@-                  | push format word
0346         movel   #thread_dispatch,a0@-    | push return addr
0347         movew   a0@(6),a0@-              | push saved sr
0348         movec   a0,msp                   | set master stack pointer
0349 #else
0350         jsr SYM (_Thread_Dispatch)       | Perform context switch
0351 #endif
0352 
0353 #if ( !defined(__mcoldfire__) )
0354 exit:   moveml  a7@+,d0-d1/a0-a1         | restore d0-d1,a0-a1
0355 #else
0356 exit:   moveml  a7@,d0-d1/a0-a1          | restore d0-d1,a0-a1
0357         lea     a7@(SAVED),a7
0358 #endif
0359 
0360 #if ( M68K_HAS_VBR == 0 )
0361         addql   #2,a7                    | pop format/id
0362 #endif /* M68K_HAS_VBR */
0363         rte                              | return to thread
0364                                          |   OR _Isr_dispatch
0365 
0366 #if ( M68K_HAS_SEPARATE_STACKS == 1 )
0367 /*
0368  *  Entry point from the outermost interrupt service routine exit.
0369  *  The current stack is the supervisor mode stack if this processor
0370  *  has separate stacks.
0371  *
0372  *    1.  save all registers not preserved across C calls.
0373  *    2.  invoke the _Thread_Dispatch routine to switch tasks
0374  *        or a signal to the currently executing task.
0375  *    3.  restore all registers not preserved across C calls.
0376  *    4.  return from interrupt
0377  */
0378 
0379 thread_dispatch:
0380 #if ( !defined(__mcoldfire__) )
0381         movml   d0-d1/a0-a1,a7@-
0382         jsr     SYM (_Thread_Dispatch)
0383         movml   a7@+,d0-d1/a0-a1
0384 #else
0385         lea     a7@(-SAVED),a7
0386         movml   d0-d1/a0-a1,a7@
0387         jsr     SYM (_Thread_Dispatch)
0388         movml   a7@,d0-d1/a0-a1
0389         lea     a7@(SAVED),a7
0390 #endif
0391 
0392 #if ( M68K_HAS_VBR == 0 )
0393         addql   #2,a7                    | pop format/id
0394 #endif /* M68K_HAS_VBR */
0395         rte
0396 #endif /* M68K_HAS_SEPARATE_STACKS */