summaryrefslogtreecommitdiffstats
path: root/c/src/exec/score/cpu/a29k/cpu_asm.S
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/exec/score/cpu/a29k/cpu_asm.S')
-rw-r--r--c/src/exec/score/cpu/a29k/cpu_asm.S491
1 files changed, 491 insertions, 0 deletions
diff --git a/c/src/exec/score/cpu/a29k/cpu_asm.S b/c/src/exec/score/cpu/a29k/cpu_asm.S
new file mode 100644
index 0000000000..a3ed2c59c3
--- /dev/null
+++ b/c/src/exec/score/cpu/a29k/cpu_asm.S
@@ -0,0 +1,491 @@
+;/* cpu_asm.c ===> cpu_asm.S or cpu_asm.s
+; *
+; * Author: Craig Lebakken <craigl@transition.com>
+; *
+; * COPYRIGHT (c) 1996 by Transition Networks Inc.
+; *
+; * To anyone who acknowledges that this file is provided "AS IS"
+; * without any express or implied warranty:
+; * permission to use, copy, modify, and distribute this file
+; * for any purpose is hereby granted without fee, provided that
+; * the above copyright notice and this notice appears in all
+; * copies, and that the name of Transition Networks not be used in
+; * advertising or publicity pertaining to distribution of the
+; * software without specific, written prior permission.
+; * Transition Networks makes no representations about the suitability
+; * of this software for any purpose.
+; *
+; *
+; * This file contains the basic algorithms for all assembly code used
+; * in an specific CPU port of RTEMS. These algorithms must be implemented
+; * in assembly language
+; *
+; * NOTE: This is supposed to be a .S or .s file NOT a C file.
+; *
+; * COPYRIGHT (c) 1989-1998.
+; * On-Line Applications Research Corporation (OAR).
+; * Copyright assigned to U.S. Government, 1994.
+; *
+; * 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$
+; */
+
+;/*
+; * This is supposed to be an assembly file. This means that system.h
+; * and cpu.h should not be included in a "real" cpu_asm file. An
+; * implementation in assembly should include "cpu_asm.h>
+; */
+
+;#include <cpu_asm.h>
+ .include "register.ah"
+ .include "amd.ah"
+ .include "pswmacro.ah"
+; .extern _bsp_exit
+;
+; push a register onto the struct
+ .macro spush, sp, reg
+ store 0, 0, reg, sp ; push register
+ add sp, sp, 4 ; adjust stack pointer
+ .endm
+; push a register onto the struct
+ .macro spushsr, sp, reg, sr
+ mfsr reg, sr
+ store 0, 0, reg, sp ; push register
+ add sp, sp, 4 ; adjust stack pointer
+ .endm
+; pop a register from the struct
+ .macro spop, reg, sp
+ load 0, 0, reg, sp
+ add sp,sp,4
+ .endm
+; pop a special register from the struct
+ .macro spopsr, sreg, reg, sp
+ load 0, 0, reg, sp
+ mtsr sreg, reg
+ add sp,sp,4
+ .endm
+;
+;/*
+; * _CPU_Context_save_fp_context
+; *
+; * This routine is responsible for saving the FP context
+; * at *fp_context_ptr. If the point to load the FP context
+; * from is changed then the pointer is modified by this routine.
+; *
+; * Sometimes a macro implementation of this is in cpu.h which dereferences
+; * the ** and a similarly named routine in this file is passed something
+; * like a (Context_Control_fp *). The general rule on making this decision
+; * is to avoid writing assembly language.
+; */
+
+;#if 0
+;void _CPU_Context_save_fp(
+; void **fp_context_ptr
+;)
+;{
+;}
+;#endif
+ .global _CPU_Context_save_fp
+_CPU_Context_save_fp:
+ jmpi lr0
+ nop
+
+;/*
+; * _CPU_Context_restore_fp_context
+; *
+; * This routine is responsible for restoring the FP context
+; * at *fp_context_ptr. If the point to load the FP context
+; * from is changed then the pointer is modified by this routine.
+; *
+; * Sometimes a macro implementation of this is in cpu.h which dereferences
+; * the ** and a similarly named routine in this file is passed something
+; * like a (Context_Control_fp *). The general rule on making this decision
+; * is to avoid writing assembly language.
+; */
+
+;#if 0
+;void _CPU_Context_restore_fp(
+; void **fp_context_ptr
+;)
+;{
+;}
+;#endif
+ .global __CPU_Context_restore_fp
+__CPU_Context_restore_fp:
+ jmpi lr0
+ nop
+
+;/* _CPU_Context_switch
+; *
+; * This routine performs a normal non-FP context switch.
+; */
+;#if 0
+;void _CPU_Context_switch(
+; Context_Control *run,
+; Context_Control *heir
+;)
+;{
+;}
+;#endif
+ .global __CPU_Context_switch
+__CPU_Context_switch:
+ asneq 106, gr1, gr1 ; syscall
+ jmpi lr0 ;
+ nop ;
+
+
+
+ .global _a29k_context_switch_sup
+_a29k_context_switch_sup:
+ add pcb,lr2,0
+ add kt1,lr3,0 ;move heir pointer to safe location
+ constn it0,SIG_SYNC
+ spush pcb,it0
+ spush pcb,gr1
+ spush pcb,rab ;push rab
+ spushsr pcb,it0,pc0 ;push specials
+ spushsr pcb,it0,pc1
+ add pcb,pcb,1*4 ;space pc2
+ spushsr pcb,it0,CHA ;push CHA
+ spushsr pcb,it0,CHD ;push CHD
+ spushsr pcb,it0,CHC ;push CHC
+ add pcb,pcb,1*4 ;space for alu
+ spushsr pcb,it0,ops ;push OPS
+ mfsr kt0,cps ;current status
+ const it1,FZ ;FZ constant
+ andn it1,kt0,it1 ;clear FZ bit
+ mtsr cps,it1 ;cps without FZ
+ add pcb,pcb,1*4 ;space for tav
+ mtsrim chc,0 ;possible DERR
+;
+ spush pcb,lr1 ;push R-stack
+ spush pcb,rfb ; support
+ spush pcb,msp ;push M-stack pnt.
+;
+ add pcb,pcb,3*4 ;space for floating point
+; spush pcb,FPStat0 ;floating point
+; spush pcb,FPStat1
+; spush pcb,FPStat2
+;
+ add pcb,pcb,4*4 ;space for IPA..Q
+;
+ mtsrim cr,29-1
+ storem 0,0,gr96,pcb ;push gr96-124, optional
+ add pcb,pcb,29*4 ;space for gr96-124
+;
+ sub it0,rfb,gr1 ;get bytes in cache
+ srl it0,it0,2 ;adjust to words
+ sub it0,it0,1
+ spush pcb,it0
+ mtsr cr,it0
+ storem 0,0,lr0,pcb ;save lr0-rfb
+;
+context_restore:
+ add pcb,kt1,0 ;pcb=heir
+ add pcb,pcb,4 ;space for signal num
+ spop gr1,pcb ;restore freeze registers
+ add gr1,gr1,0 ;alu op
+ add pcb,pcb,9*4 ;move past freeze registers
+ add pcb,pcb,1*4 ;space for tav
+ spop lr1,pcb
+ spop rfb,pcb
+ spop msp,pcb
+; spop FPStat0,pcb
+; spop FPStat1,pcb
+; spop FPStat2,pcb
+ add pcb,pcb,3*4 ;space for floating point
+ add pcb,pcb,4*4 ;space for IPA..Q
+ mtsrim cr,29-1
+ loadm 0,0,gr96,pcb ;pop gr96-gr124
+ add pcb,pcb,29*4 ;space for gr96-124
+
+ spop it1,pcb ;pop locals count
+ mtsr cr,it1
+ loadm 0,0,lr0,pcb ;load locals
+
+ add pcb,kt1,0 ;pcb=heir
+ mtsr cps,kt0 ;cps with FZ
+ nop
+ add pcb,pcb,4 ;space for signal num
+ spop gr1,pcb ;restore freeze registers
+ add gr1,gr1,0 ;alu op
+ spop rab,pcb
+ spopsr pc0,it1,pcb
+ spopsr pc1,it1,pcb
+ add pcb,pcb,4 ;space for pc2
+ spopsr CHA,it1,pcb
+ spopsr CHD,it1,pcb
+ spopsr CHC,it1,pcb
+ add pcb,pcb,4 ;space for alu
+ spopsr ops,it1,pcb
+ nop
+ iret
+
+
+;/*
+; * _CPU_Context_restore
+; *
+; * This routine is generally used only to restart self in an
+; * efficient manner. It may simply be a label in _CPU_Context_switch.
+; *
+; * NOTE: May be unnecessary to reload some registers.
+; */
+;#if 0
+;void _CPU_Context_restore(
+; Context_Control *new_context
+;)
+;{
+;}
+;#endif
+
+ .global __CPU_Context_restore
+__CPU_Context_restore:
+ asneq 107, gr1, gr1 ; syscall
+ jmpi lr0 ;
+ nop ;
+
+ .global _a29k_context_restore_sup
+_a29k_context_restore_sup:
+ add kt1,lr2,0 ;kt1 = restore context
+ mfsr kt0,cps ;current status
+ const it1,FZ ;FZ constant
+ andn it1,kt0,it1 ;clear FZ bit
+ mtsr cps,it1 ;cps without FZ
+ jmp context_restore
+ nop
+
+ .global _a29k_context_save_sup
+_a29k_context_save_sup:
+ add pcb,lr2,0
+ constn it0,SIG_SYNC
+ spush pcb,it0
+ spush pcb,gr1
+ spush pcb,rab ;push rab
+ spushsr pcb,it0,pc0 ;push specials
+ spushsr pcb,it0,pc1
+ add pcb,pcb,1*4 ;space pc2
+ spushsr pcb,it0,CHA ;push CHA
+ spushsr pcb,it0,CHD ;push CHD
+ spushsr pcb,it0,CHC ;push CHC
+ add pcb,pcb,1*4 ;space for alu
+ spushsr pcb,it0,ops ;push OPS
+ mfsr it0,cps ;current status
+SaveFZState it1,it2
+ add pcb,pcb,1*4 ;space for tav
+ mtsrim chc,0 ;possible DERR
+;
+ spush pcb,lr1 ;push R-stack
+ spush pcb,rfb ; support
+ spush pcb,msp ;push M-stack pnt.
+;
+ spush pcb,FPStat0 ;floating point
+ spush pcb,FPStat1
+ spush pcb,FPStat2
+;
+ add pcb,pcb,4*4 ;space for IPA..Q
+;
+ mtsrim cr,29-1
+ storem 0,0,gr96,pcb ;push gr96-124, optional
+ add pcb,pcb,29*4 ;space for gr96-124
+;
+ sub kt0,rfb,gr1 ;get bytes in cache
+ srl kt0,kt0,2 ;adjust to words
+ sub kt0,kt0,1
+ spush pcb,kt0 ;push number of words
+ mtsr cr,kt0
+ storem 0,0,lr0,pcb ;save lr0-rfb
+;
+ mtsr cps,it0 ;cps with FZ
+RestoreFZState it1,it2
+
+ nop
+ nop
+ nop
+;
+ iret
+;
+
+ .global __CPU_Context_save
+__CPU_Context_save:
+ asneq 108, gr1, gr1 ; syscall
+ jmpi lr0 ;
+ nop ;
+
+
+;/* void __ISR_Handler()
+; *
+; * This routine provides the RTEMS interrupt management.
+; *
+; */
+
+;#if 0
+;void _ISR_Handler()
+;{
+; /*
+; * This discussion ignores a lot of the ugly details in a real
+; * implementation such as saving enough registers/state to be
+; * able to do something real. Keep in mind that the goal is
+; * to invoke a user's ISR handler which is written in C and
+; * uses a certain set of registers.
+; *
+; * Also note that the exact order is to a large extent flexible.
+; * Hardware will dictate a sequence for a certain subset of
+; * _ISR_Handler while requirements for setting
+; */
+
+; /*
+; * At entry to "common" _ISR_Handler, the vector number must be
+; * available. On some CPUs the hardware puts either the vector
+; * number or the offset into the vector table for this ISR in a
+; * known place. If the hardware does not give us this information,
+; * then the assembly portion of RTEMS for this port will contain
+; * a set of distinct interrupt entry points which somehow place
+; * the vector number in a known place (which is safe if another
+; * interrupt nests this one) and branches to _ISR_Handler.
+; *
+; * save some or all context on stack
+; * may need to save some special interrupt information for exit
+; *
+; * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
+; * if ( _ISR_Nest_level == 0 )
+; * switch to software interrupt stack
+; * #endif
+; *
+; * _ISR_Nest_level++;
+; *
+; * _Thread_Dispatch_disable_level++;
+; *
+; * (*_ISR_Vector_table[ vector ])( vector );
+; *
+; * --_ISR_Nest_level;
+; *
+; * if ( _ISR_Nest_level )
+; * goto the label "exit interrupt (simple case)"
+; *
+; * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
+; * restore stack
+; * #endif
+; *
+; * if ( !_Context_Switch_necessary )
+; * goto the label "exit interrupt (simple case)"
+; *
+; * if ( !_ISR_Signals_to_thread_executing )
+; * goto the label "exit interrupt (simple case)"
+; *
+; * call _Thread_Dispatch() or prepare to return to _ISR_Dispatch
+; *
+; * prepare to get out of interrupt
+; * return from interrupt (maybe to _ISR_Dispatch)
+; *
+; * LABEL "exit interrupt (simple case):
+; * prepare to get out of interrupt
+; * return from interrupt
+; */
+;}
+;#endif
+; .global __ISR_Handler
+;__ISR_Handler:
+; jmpi lr0
+; nop
+
+ .global _a29k_getops
+_a29k_getops:
+ asneq 113, gr96, gr96
+ jmpi lr0
+ nop
+
+ .global _a29k_getops_sup
+_a29k_getops_sup:
+ mfsr gr96, ops ; caller wants ops
+ iret
+ nop
+
+ .global _a29k_disable
+_a29k_disable:
+ asneq 110, gr96, gr96
+ jmpi lr0
+ nop
+
+ .global _a29k_disable_sup
+_a29k_disable_sup:
+ mfsr kt0, ops
+ add gr96, kt0, 0 ; return ops to caller
+ const kt1, (DI | TD)
+ consth kt1, (DI | TD)
+ or kt1, kt0, kt1
+ mtsr ops, kt1
+ iret
+ nop
+
+ .global _a29k_disable_all
+_a29k_disable_all:
+ asneq 112, gr96, gr96
+ jmpi lr0
+ nop
+
+ .global _a29k_disable_all_sup
+_a29k_disable_all_sup:
+ mfsr kt0, ops
+ const kt1, (DI | TD)
+ consth kt1, (DI | TD)
+ or kt1, kt0, kt1
+ mtsr ops, kt1
+ iret
+ nop
+
+ .global _a29k_enable_all
+_a29k_enable_all:
+ asneq 111, gr96, gr96
+ jmpi lr0
+ nop
+
+ .global _a29k_enable_all_sup
+_a29k_enable_all_sup:
+ mfsr kt0, ops
+ const kt1, (DI | TD)
+ consth kt1, (DI | TD)
+ andn kt1, kt0, kt1
+ mtsr ops, kt1
+ iret
+ nop
+
+ .global _a29k_enable
+_a29k_enable:
+ asneq 109, gr96, gr96
+ jmpi lr0
+ nop
+
+ .global _a29k_enable_sup
+_a29k_enable_sup:
+ mfsr kt0, ops
+ const kt1, (DI | TD)
+ consth kt1, (DI | TD)
+ and kt3, lr2, kt1
+ andn kt0, kt0, kt1
+ or kt1, kt0, kt3
+ mtsr ops, kt1
+ iret
+ nop
+
+ .global _a29k_halt
+_a29k_halt:
+ halt
+ jmp _a29k_halt
+ nop
+
+ .global _a29k_super_mode
+_a29k_super_mode:
+ mfsr gr96, ops
+ or gr96, gr96, 0x10
+ mtsr ops, gr96
+ iret
+ nop
+
+ .global _a29k_as70
+_a29k_as70:
+ asneq 70,gr96,gr96
+ jmpi lr0
+ nop