1*10465441SEvalZero/* 2*10465441SEvalZero * File : context_gcc.S 3*10465441SEvalZero * This file is part of RT-Thread RTOS 4*10465441SEvalZero * COPYRIGHT (C) 2006-2011, RT-Thread Development Team 5*10465441SEvalZero * 6*10465441SEvalZero * The license and distribution terms for this file may be 7*10465441SEvalZero * found in the file LICENSE in this distribution or at 8*10465441SEvalZero * http://www.rt-thread.org/license/LICENSE 9*10465441SEvalZero * 10*10465441SEvalZero * Change Logs: 11*10465441SEvalZero * Date Author Notes 12*10465441SEvalZero * 2011-02-14 aozima first implementation for Nios II. 13*10465441SEvalZero * 2011-02-20 aozima fix context&switch bug. 14*10465441SEvalZero */ 15*10465441SEvalZero 16*10465441SEvalZero/** 17*10465441SEvalZero * @addtogroup NIOS_II 18*10465441SEvalZero */ 19*10465441SEvalZero/*@{*/ 20*10465441SEvalZero 21*10465441SEvalZero.text 22*10465441SEvalZero 23*10465441SEvalZero.set noat 24*10465441SEvalZero 25*10465441SEvalZero/* 26*10465441SEvalZero * rt_base_t rt_hw_interrupt_disable(); 27*10465441SEvalZero */ 28*10465441SEvalZero.global rt_hw_interrupt_disable 29*10465441SEvalZero.type rt_hw_interrupt_disable, %function 30*10465441SEvalZerort_hw_interrupt_disable: 31*10465441SEvalZero rdctl r2, status /* return status */ 32*10465441SEvalZero wrctl status, zero /* disable interrupt */ 33*10465441SEvalZero ret 34*10465441SEvalZero 35*10465441SEvalZero/* 36*10465441SEvalZero * void rt_hw_interrupt_enable(rt_base_t level); 37*10465441SEvalZero */ 38*10465441SEvalZero.global rt_hw_interrupt_enable 39*10465441SEvalZero.type rt_hw_interrupt_enable, %function 40*10465441SEvalZerort_hw_interrupt_enable: 41*10465441SEvalZero wrctl status, r4 /* enable interrupt by argument */ 42*10465441SEvalZero ret 43*10465441SEvalZero 44*10465441SEvalZero/* void rt_hw_context_switch_interrupt_do(void) */ 45*10465441SEvalZero.global rt_hw_context_switch_interrupt_do 46*10465441SEvalZero.type rt_hw_context_switch_interrupt_do, %function 47*10465441SEvalZerort_hw_context_switch_interrupt_do: 48*10465441SEvalZero /* save from thread */ 49*10465441SEvalZero addi sp,sp,-72 50*10465441SEvalZero 51*10465441SEvalZero /* frist save r2,so that save status */ 52*10465441SEvalZero stw r2, 4(sp) 53*10465441SEvalZero 54*10465441SEvalZero /* save status */ 55*10465441SEvalZero /* when the interrupt happen,the interrupt is enable */ 56*10465441SEvalZero movi r2, 1 57*10465441SEvalZero stw r2, 68(sp) /* status */ 58*10465441SEvalZero 59*10465441SEvalZero stw r3, 8(sp) 60*10465441SEvalZero stw r4, 12(sp) 61*10465441SEvalZero 62*10465441SEvalZero /* get & save from thread pc */ 63*10465441SEvalZero ldw r4,%gprel(rt_current_thread_entry)(gp) 64*10465441SEvalZero stw r4, 0(sp) /* thread pc */ 65*10465441SEvalZero 66*10465441SEvalZero stw r5, 16(sp) 67*10465441SEvalZero stw r6, 20(sp) 68*10465441SEvalZero stw r7, 24(sp) 69*10465441SEvalZero 70*10465441SEvalZero stw r16, 28(sp) 71*10465441SEvalZero stw r17, 32(sp) 72*10465441SEvalZero stw r18, 36(sp) 73*10465441SEvalZero stw r19, 40(sp) 74*10465441SEvalZero stw r20, 44(sp) 75*10465441SEvalZero stw r21, 48(sp) 76*10465441SEvalZero stw r22, 52(sp) 77*10465441SEvalZero stw r23, 56(sp) 78*10465441SEvalZero 79*10465441SEvalZero stw fp, 60(sp) 80*10465441SEvalZero stw ra, 64(sp) 81*10465441SEvalZero 82*10465441SEvalZero /* save from thread sp */ 83*10465441SEvalZero /* rt_interrupt_from_thread = &from_thread->sp */ 84*10465441SEvalZero ldw r4, %gprel(rt_interrupt_from_thread)(gp) 85*10465441SEvalZero /* *r4(from_thread->sp) = sp */ 86*10465441SEvalZero stw sp, (r4) 87*10465441SEvalZero 88*10465441SEvalZero /* clear rt_thread_switch_interrupt_flag */ 89*10465441SEvalZero /* rt_thread_switch_interrupt_flag = 0 */ 90*10465441SEvalZero stw zero,%gprel(rt_thread_switch_interrupt_flag)(gp) 91*10465441SEvalZero 92*10465441SEvalZero /* load to thread sp */ 93*10465441SEvalZero /* r4 = rt_interrupt_to_thread(&to_thread->sp) */ 94*10465441SEvalZero ldw r4, %gprel(rt_interrupt_to_thread)(gp) 95*10465441SEvalZero /* sp = to_thread->sp */ 96*10465441SEvalZero ldw sp, (r4) 97*10465441SEvalZero 98*10465441SEvalZero ldw r2, 68(sp) /* status */ 99*10465441SEvalZero wrctl estatus, r2 100*10465441SEvalZero 101*10465441SEvalZero ldw ea, 0(sp) /* thread pc */ 102*10465441SEvalZero ldw r2, 4(sp) 103*10465441SEvalZero ldw r3, 8(sp) 104*10465441SEvalZero ldw r4, 12(sp) 105*10465441SEvalZero ldw r5, 16(sp) 106*10465441SEvalZero ldw r6, 20(sp) 107*10465441SEvalZero ldw r7, 24(sp) 108*10465441SEvalZero 109*10465441SEvalZero ldw r16, 28(sp) 110*10465441SEvalZero ldw r17, 32(sp) 111*10465441SEvalZero ldw r18, 36(sp) 112*10465441SEvalZero ldw r19, 40(sp) 113*10465441SEvalZero ldw r20, 44(sp) 114*10465441SEvalZero ldw r21, 48(sp) 115*10465441SEvalZero ldw r22, 52(sp) 116*10465441SEvalZero ldw r23, 56(sp) 117*10465441SEvalZero 118*10465441SEvalZero ldw fp, 60(sp) 119*10465441SEvalZero ldw ra, 64(sp) 120*10465441SEvalZero 121*10465441SEvalZero addi sp, sp, 72 122*10465441SEvalZero 123*10465441SEvalZero /* estatus --> status,ea --> pc */ 124*10465441SEvalZero eret 125*10465441SEvalZero 126*10465441SEvalZero/* 127*10465441SEvalZero * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); 128*10465441SEvalZero * r4: from 129*10465441SEvalZero * r5: to 130*10465441SEvalZero */ 131*10465441SEvalZero.global rt_hw_context_switch 132*10465441SEvalZero.type rt_hw_context_switch, %function 133*10465441SEvalZerort_hw_context_switch: 134*10465441SEvalZero /* save from thread */ 135*10465441SEvalZero addi sp,sp,-72 136*10465441SEvalZero 137*10465441SEvalZero /* frist save r2,so that save status */ 138*10465441SEvalZero stw r2, 4(sp) 139*10465441SEvalZero 140*10465441SEvalZero /* save status */ 141*10465441SEvalZero rdctl r2, status 142*10465441SEvalZero stw r2, 68(sp) /* status */ 143*10465441SEvalZero 144*10465441SEvalZero stw ra, 0(sp) /* return from rt_hw_context_switch */ 145*10465441SEvalZero stw r3, 8(sp) 146*10465441SEvalZero stw r4, 12(sp) 147*10465441SEvalZero stw r5, 16(sp) 148*10465441SEvalZero stw r6, 20(sp) 149*10465441SEvalZero stw r7, 24(sp) 150*10465441SEvalZero 151*10465441SEvalZero stw r16, 28(sp) 152*10465441SEvalZero stw r17, 32(sp) 153*10465441SEvalZero stw r18, 36(sp) 154*10465441SEvalZero stw r19, 40(sp) 155*10465441SEvalZero stw r20, 44(sp) 156*10465441SEvalZero stw r21, 48(sp) 157*10465441SEvalZero stw r22, 52(sp) 158*10465441SEvalZero stw r23, 56(sp) 159*10465441SEvalZero 160*10465441SEvalZero stw fp, 60(sp) 161*10465441SEvalZero stw ra, 64(sp) 162*10465441SEvalZero 163*10465441SEvalZero /* save form thread sp */ 164*10465441SEvalZero /* from_thread->sp(r4) = sp */ 165*10465441SEvalZero stw sp, (r4) 166*10465441SEvalZero 167*10465441SEvalZero /* update rt_interrupt_from_thread */ 168*10465441SEvalZero /* rt_interrupt_from_thread = r4(from_thread->sp) */ 169*10465441SEvalZero stw r4,%gprel(rt_interrupt_from_thread)(gp) 170*10465441SEvalZero 171*10465441SEvalZero /* update rt_interrupt_to_thread */ 172*10465441SEvalZero /* rt_interrupt_to_thread = r5 */ 173*10465441SEvalZero stw r5,%gprel(rt_interrupt_to_thread)(gp) 174*10465441SEvalZero 175*10465441SEvalZero /* get to thread sp */ 176*10465441SEvalZero /* sp = rt_interrupt_to_thread(r5:to_thread->sp) */ 177*10465441SEvalZero ldw sp, (r5) 178*10465441SEvalZero 179*10465441SEvalZero ldw r2, 68(sp) /* status */ 180*10465441SEvalZero wrctl estatus, r2 181*10465441SEvalZero 182*10465441SEvalZero ldw ea, 0(sp) /* thread pc */ 183*10465441SEvalZero 184*10465441SEvalZero ldw r2, 4(sp) 185*10465441SEvalZero ldw r3, 8(sp) 186*10465441SEvalZero ldw r4, 12(sp) 187*10465441SEvalZero ldw r5, 16(sp) 188*10465441SEvalZero ldw r6, 20(sp) 189*10465441SEvalZero ldw r7, 24(sp) 190*10465441SEvalZero 191*10465441SEvalZero ldw r16, 28(sp) 192*10465441SEvalZero ldw r17, 32(sp) 193*10465441SEvalZero ldw r18, 36(sp) 194*10465441SEvalZero ldw r19, 40(sp) 195*10465441SEvalZero ldw r20, 44(sp) 196*10465441SEvalZero ldw r21, 48(sp) 197*10465441SEvalZero ldw r22, 52(sp) 198*10465441SEvalZero ldw r23, 56(sp) 199*10465441SEvalZero 200*10465441SEvalZero ldw fp, 60(sp) 201*10465441SEvalZero ldw ra, 64(sp) 202*10465441SEvalZero 203*10465441SEvalZero addi sp, sp, 72 204*10465441SEvalZero 205*10465441SEvalZero /* estatus --> status,ea --> pc */ 206*10465441SEvalZero eret 207*10465441SEvalZero 208*10465441SEvalZero/* 209*10465441SEvalZero * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); 210*10465441SEvalZero * r4: from 211*10465441SEvalZero * r5: to 212*10465441SEvalZero */ 213*10465441SEvalZero.global rt_hw_context_switch_interrupt 214*10465441SEvalZero.type rt_hw_context_switch_interrupt, %function 215*10465441SEvalZerort_hw_context_switch_interrupt: 216*10465441SEvalZero /* if( rt_thread_switch_interrupt_flag != 0 ) _from_thread_not_change */ 217*10465441SEvalZero ldw r2,%gprel(rt_thread_switch_interrupt_flag)(gp) 218*10465441SEvalZero bne r2,zero,_from_thread_not_change 219*10465441SEvalZero 220*10465441SEvalZero_from_thread_change: 221*10465441SEvalZero /* save ea -> rt_current_thread_entry */ 222*10465441SEvalZero addi ea,ea,-4 223*10465441SEvalZero stw ea,%gprel(rt_current_thread_entry)(gp) 224*10465441SEvalZero 225*10465441SEvalZero /* set rt_thread_switch_interrupt_flag to 1 */ 226*10465441SEvalZero movi r2, 1 227*10465441SEvalZero stw r2,%gprel(rt_thread_switch_interrupt_flag)(gp) 228*10465441SEvalZero 229*10465441SEvalZero /* update rt_interrupt_from_thread */ 230*10465441SEvalZero stw r4,%gprel(rt_interrupt_from_thread)(gp) 231*10465441SEvalZero 232*10465441SEvalZero_from_thread_not_change: 233*10465441SEvalZero /* update rt_interrupt_to_thread */ 234*10465441SEvalZero stw r5,%gprel(rt_interrupt_to_thread)(gp) 235*10465441SEvalZero 236*10465441SEvalZero ret 237*10465441SEvalZero 238*10465441SEvalZero/* 239*10465441SEvalZero * void rt_hw_context_switch_to(rt_uint32 to); 240*10465441SEvalZero * r4: to 241*10465441SEvalZero */ 242*10465441SEvalZero.global rt_hw_context_switch_to 243*10465441SEvalZero.type rt_hw_context_switch_to, %function 244*10465441SEvalZerort_hw_context_switch_to: 245*10465441SEvalZero /* save to thread */ 246*10465441SEvalZero stw r4,%gprel(rt_interrupt_to_thread)(gp) 247*10465441SEvalZero 248*10465441SEvalZero /* get sp */ 249*10465441SEvalZero ldw sp, (r4) // sp = *r4 250*10465441SEvalZero 251*10465441SEvalZero ldw r2, 68(sp) /* status */ 252*10465441SEvalZero wrctl estatus, r2 253*10465441SEvalZero 254*10465441SEvalZero ldw ea, 0(sp) /* thread entry */ 255*10465441SEvalZero 256*10465441SEvalZero ldw r2, 4(sp) 257*10465441SEvalZero ldw r3, 8(sp) 258*10465441SEvalZero ldw r4, 12(sp) 259*10465441SEvalZero ldw r5, 16(sp) 260*10465441SEvalZero ldw r6, 20(sp) 261*10465441SEvalZero ldw r7, 24(sp) 262*10465441SEvalZero 263*10465441SEvalZero ldw r16, 28(sp) 264*10465441SEvalZero ldw r17, 32(sp) 265*10465441SEvalZero ldw r18, 36(sp) 266*10465441SEvalZero ldw r19, 40(sp) 267*10465441SEvalZero ldw r20, 44(sp) 268*10465441SEvalZero ldw r21, 48(sp) 269*10465441SEvalZero ldw r22, 52(sp) 270*10465441SEvalZero ldw r23, 56(sp) 271*10465441SEvalZero 272*10465441SEvalZero ldw fp, 60(sp) 273*10465441SEvalZero ldw ra, 64(sp) 274*10465441SEvalZero 275*10465441SEvalZero addi sp, sp, 72 276*10465441SEvalZero 277*10465441SEvalZero /* estatus --> status,ea --> pc */ 278*10465441SEvalZero eret 279*10465441SEvalZero 280*10465441SEvalZero/*@}*/ 281