[ac7d5ef0] | 1 | /* cpu_asm.s |
---|
| 2 | * |
---|
| 3 | * This file contains all assembly code for the i960CA implementation |
---|
| 4 | * of RTEMS. |
---|
| 5 | * |
---|
[08311cc3] | 6 | * COPYRIGHT (c) 1989-1999. |
---|
[ac7d5ef0] | 7 | * On-Line Applications Research Corporation (OAR). |
---|
| 8 | * |
---|
[98e4ebf5] | 9 | * The license and distribution terms for this file may be |
---|
| 10 | * found in the file LICENSE in this distribution or at |
---|
[03f2154e] | 11 | * http://www.OARcorp.com/rtems/license.html. |
---|
[ac7d5ef0] | 12 | * |
---|
| 13 | * $Id$ |
---|
| 14 | */ |
---|
[f2180e0f] | 15 | .data |
---|
| 16 | .align 4 |
---|
| 17 | _soft_reset_reg_save: |
---|
| 18 | .word 0 |
---|
| 19 | .word 0 |
---|
| 20 | .word 0 |
---|
| 21 | .word 0 |
---|
| 22 | _ISR_reg_save: |
---|
| 23 | .word 0 |
---|
| 24 | .word 0 |
---|
| 25 | .word 0 |
---|
| 26 | .word 0 |
---|
| 27 | .word 0 |
---|
| 28 | .word 0 |
---|
[ac7d5ef0] | 29 | |
---|
| 30 | .text |
---|
| 31 | /* |
---|
| 32 | * Format of i960ca Register structure |
---|
| 33 | */ |
---|
| 34 | |
---|
| 35 | .set REG_R0_PFP , 0 # (r0) Previous Frame Pointer |
---|
| 36 | .set REG_R1_SP , REG_R0_PFP+4 # (r1) Stack Pointer |
---|
| 37 | .set REG_PC , REG_R1_SP+4 # (pc) Processor Controls |
---|
| 38 | .set REG_G8 , REG_PC+4 # (g8) Global Register 8 |
---|
| 39 | .set REG_G9 , REG_G8+4 # (g9) Global Register 9 |
---|
| 40 | .set REG_G10 , REG_G9+4 # (g10) Global Register 10 |
---|
| 41 | .set REG_G11 , REG_G10+4 # (g11) Global Register 11 |
---|
| 42 | .set REG_G12 , REG_G11+4 # (g12) Global Register 12 |
---|
| 43 | .set REG_G13 , REG_G12+4 # (g13) Global Register 13 |
---|
| 44 | .set REG_G14 , REG_G13+4 # (g14) Global Register 14 |
---|
| 45 | .set REG_G15_FP , REG_G14+4 # (g15) Global Register 15 |
---|
| 46 | .set SIZE_REGS , REG_G15_FP+4 # size of cpu_context_registers |
---|
| 47 | # structure |
---|
| 48 | |
---|
| 49 | /* |
---|
| 50 | * void _CPU_Context_switch( run_context, heir_context ) |
---|
| 51 | * |
---|
| 52 | * This routine performs a normal non-FP context. |
---|
| 53 | */ |
---|
| 54 | .align 4 |
---|
| 55 | .globl __CPU_Context_switch |
---|
| 56 | |
---|
| 57 | __CPU_Context_switch: |
---|
| 58 | modpc 0,0,g2 # get old intr level (PC) |
---|
| 59 | st g2,REG_PC(g0) # save pc |
---|
| 60 | stq g8,REG_G8(g0) # save g8-g11 |
---|
| 61 | stq g12,REG_G12(g0) # save g12-g15 |
---|
| 62 | stl pfp,REG_R0_PFP(g0) # save pfp, sp |
---|
| 63 | |
---|
| 64 | restore: flushreg # flush register cache |
---|
| 65 | ldconst 0x001f0000,g2 # g2 = PC mask |
---|
| 66 | ld REG_PC(g1),g3 # thread->Regs.pc = pc; |
---|
| 67 | ldq REG_G12(g1),g12 # restore g12-g15 |
---|
| 68 | ldl REG_R0_PFP(g1),pfp # restore pfp, sp |
---|
| 69 | ldq REG_G8(g1),g8 # restore g8-g11 |
---|
| 70 | modpc 0,g2,g3 # restore PC register |
---|
| 71 | ret |
---|
| 72 | |
---|
| 73 | /* |
---|
| 74 | * void _CPU_Context_restore( new_context ) |
---|
| 75 | * |
---|
| 76 | * This routine performs a normal non-FP context. |
---|
| 77 | */ |
---|
| 78 | |
---|
| 79 | .globl __CPU_Context_restore |
---|
| 80 | __CPU_Context_restore: |
---|
| 81 | mov g0,g1 # g0 = _Thread_executing |
---|
| 82 | b restore |
---|
| 83 | |
---|
| 84 | /*PAGE |
---|
| 85 | * void _CPU_Context_save_fp_context( &fp_context_ptr ) |
---|
| 86 | * void _CPU_Context_restore_fp_context( &fp_context_ptr ) |
---|
| 87 | * |
---|
| 88 | * There is currently no hardware floating point for the i960. |
---|
| 89 | */ |
---|
| 90 | |
---|
| 91 | .globl __CPU_Context_save_fp |
---|
| 92 | .globl __CPU_Context_restore_fp |
---|
| 93 | __CPU_Context_save_fp: |
---|
| 94 | __CPU_Context_restore_fp: |
---|
| 95 | #if ( I960_HAS_FPU == 1 ) |
---|
| 96 | #error "Floating point support for i960 family has been implemented!!!" |
---|
| 97 | #endif |
---|
| 98 | ret |
---|
| 99 | |
---|
| 100 | /*PAGE |
---|
| 101 | * void __ISR_Handler() |
---|
| 102 | * |
---|
| 103 | * This routine provides the RTEMS interrupt management. |
---|
| 104 | * |
---|
| 105 | * Input parameters: NONE |
---|
| 106 | * |
---|
| 107 | * Output parameters: NONE |
---|
| 108 | * |
---|
| 109 | * NOTE: |
---|
| 110 | * Upon entry, the supervisor stack will contain a stack frame |
---|
| 111 | * back to the interrupted thread and the interrupt stack will contain |
---|
| 112 | * an interrupt stack frame. If dispatching is enabled, this |
---|
| 113 | * is the outer most interrupt, and (a context switch is necessary or |
---|
| 114 | * the current thread has signals), then set up the supervisor stack to |
---|
| 115 | * transfer control to the interrupt dispatcher. |
---|
| 116 | */ |
---|
| 117 | |
---|
| 118 | .globl __ISR_Handler |
---|
| 119 | __ISR_Handler: |
---|
| 120 | #ldconst 1,r8 |
---|
| 121 | #modpc 0,r8,r8 # enable tracing |
---|
| 122 | |
---|
| 123 | # r4 = &_Thread_Dispatch_disable_level |
---|
| 124 | ld __Thread_Dispatch_disable_level,r4 |
---|
| 125 | movl g0,r8 # save g0-g1 |
---|
| 126 | |
---|
| 127 | ld -16+8(fp),g0 # g0 = vector number |
---|
| 128 | movl g2,r10 # save g2-g3 |
---|
| 129 | |
---|
| 130 | ld __ISR_Nest_level,r5 # r5 = &_Isr_nest_level |
---|
| 131 | mov g14,r7 # save g14 |
---|
| 132 | |
---|
| 133 | lda 0,g14 # NOT Branch and Link |
---|
| 134 | movl g4,r12 # save g4-g5 |
---|
| 135 | |
---|
| 136 | lda 1(r4),r4 # increment dispatch disable level |
---|
| 137 | movl g6,r14 # save g6-g7 |
---|
| 138 | |
---|
[f2180e0f] | 139 | stq g8, _ISR_reg_save # save g8-g11 |
---|
| 140 | stl g12, _ISR_reg_save+16 # save g12-g13 |
---|
| 141 | |
---|
[ac7d5ef0] | 142 | ld __ISR_Vector_table[g0*4],g1 # g1 = Users handler |
---|
| 143 | addo 1,r5,r5 # increment ISR level |
---|
| 144 | |
---|
| 145 | st r4,__Thread_Dispatch_disable_level |
---|
| 146 | # one ISR nest level deeper |
---|
| 147 | subo 1,r4,r4 # decrement dispatch disable level |
---|
| 148 | |
---|
| 149 | st r5,__ISR_Nest_level # disable multitasking |
---|
| 150 | subo 1,r5,r5 # decrement ISR nest level |
---|
| 151 | |
---|
| 152 | callx (g1) # invoke user ISR |
---|
| 153 | |
---|
| 154 | # unnest multitasking |
---|
| 155 | st r5,__ISR_Nest_level # one less ISR nest level |
---|
| 156 | cmpobne.f 0,r4,exit # If dispatch disabled, exit |
---|
| 157 | ldl -16(fp),g0 # g0 = threads PC reg |
---|
| 158 | # g1 = threads AC reg |
---|
| 159 | ld __Context_Switch_necessary,r6 |
---|
| 160 | # r6 = Is thread switch necessary? |
---|
| 161 | bbs.f 13,g0,exit # not outer level, then exit |
---|
| 162 | cmpobne.f 0,r6,bframe # Switch necessary? |
---|
| 163 | |
---|
| 164 | ld __ISR_Signals_to_thread_executing,g2 |
---|
| 165 | # signals sent to Run_thread |
---|
| 166 | # while in interrupt handler? |
---|
| 167 | cmpobe.f 0,g2,exit # No, then exit |
---|
| 168 | |
---|
| 169 | bframe: mov 0,g2 |
---|
| 170 | st g2,__ISR_Signals_to_thread_executing |
---|
| 171 | |
---|
| 172 | ldconst 0x1f0000,g2 # g2 = intr disable mask |
---|
| 173 | mov g2,g3 # g3 = new intr level |
---|
| 174 | modpc 0,g2,g3 # set new level |
---|
| 175 | |
---|
| 176 | andnot 7,pfp,r4 # r4 = pfp without ret type |
---|
| 177 | flushreg # flush registers |
---|
| 178 | # push _Isr_dispatch ret frame |
---|
| 179 | # build ISF in r4-r6 |
---|
| 180 | ldconst 64,g2 # g2 = size of stack frame |
---|
| 181 | ld 4(r4),g3 # g3 = previous sp |
---|
| 182 | addo g2,g3,r5 # r5 = _Isr_dispatch SP |
---|
| 183 | lda __ISR_Dispatch,r6 # r6 = _Isr_dispatch entry |
---|
| 184 | stt r4,(g3) # set _Isr_dispatch ret info |
---|
| 185 | st g1,16(g3) # set r4 = AC for ISR disp |
---|
| 186 | or 7,g3,pfp # pfp to _Isr_dispatch |
---|
[e54a7d33] | 187 | flushreg |
---|
| 188 | b exit1 |
---|
| 189 | exit: st r4,__Thread_Dispatch_disable_level |
---|
| 190 | exit1: mov r7,g14 # restore g14 |
---|
[ac7d5ef0] | 191 | movq r8,g0 # restore g0-g3 |
---|
| 192 | movq r12,g4 # restore g4-g7 |
---|
[f2180e0f] | 193 | ldq _ISR_reg_save, g8 # restore g8-g11 |
---|
| 194 | ldl _ISR_reg_save+16, g12 # restore g12-g13 |
---|
[ac7d5ef0] | 195 | ret |
---|
| 196 | |
---|
| 197 | |
---|
| 198 | /*PAGE |
---|
| 199 | * |
---|
| 200 | * void __ISR_Dispatch() |
---|
| 201 | * |
---|
| 202 | * Entry point from the outermost interrupt service routine exit. |
---|
| 203 | * The current stack is the supervisor mode stack. |
---|
| 204 | */ |
---|
| 205 | |
---|
| 206 | __ISR_Dispatch: |
---|
| 207 | mov g14,r7 |
---|
| 208 | mov 0,g14 |
---|
| 209 | movq g0,r8 |
---|
| 210 | movq g4,r12 |
---|
| 211 | call __Thread_Dispatch |
---|
| 212 | |
---|
| 213 | ldconst -1,r5 # r5 = reload mask |
---|
| 214 | modac r5,r4,r4 # restore threads AC register |
---|
| 215 | mov r7,g14 |
---|
| 216 | movq r8,g0 |
---|
| 217 | movq r12,g4 |
---|
| 218 | ret |
---|
[f2180e0f] | 219 | |
---|
| 220 | |
---|
| 221 | /*PAGE |
---|
| 222 | * |
---|
| 223 | * void __i960_soft_reset_asm |
---|
| 224 | * |
---|
| 225 | * Flush the register cache and save the important (fp, pfp, sp) registers, |
---|
| 226 | * which are clobbered by the reinit operation. (Not documented, but it happens). |
---|
| 227 | */ |
---|
| 228 | |
---|
| 229 | .globl __i960_soft_reset_asm |
---|
| 230 | __i960_soft_reset_asm: |
---|
| 231 | flushreg # flush register cache |
---|
| 232 | mov fp, r4 |
---|
| 233 | mov pfp, r5 |
---|
| 234 | mov sp, r6 |
---|
| 235 | stt r4, _soft_reset_reg_save # save fp, pfp, sp |
---|
| 236 | lda __i960_reset_done, r4 |
---|
| 237 | ldconst 0x300, r5 |
---|
| 238 | sysctl r5, r4, g0 # reinit: clobbers almost all registers |
---|
| 239 | __i960_reset_done: |
---|
| 240 | ldt _soft_reset_reg_save, r4 # restore fp, pfp, sp |
---|
| 241 | mov r4, fp |
---|
| 242 | mov r5, pfp |
---|
| 243 | mov r6, sp |
---|
| 244 | ret |
---|