⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ppctrap.s

📁 可用于嵌入式编程学习
💻 S
📖 第 1 页 / 共 5 页
字号:
    cmpwi   r4, 0                       // Check if it's zero.
    beq     CheckRunList                // If no KCResched, go look at runlist

    li      r3, 0                       // load a constant 0
    stw     r3, dwKCRes(0)              // Write 0 to KCResched Flag
    bl      KCNextThread                // Call KC Sceduler
    lwz     r4, dwKCRes(0)              // Load value of KCResched after func
    cmpwi   r4, 0                       // Compare KCResched to 0
    bne     CheckResched                // If it's non-zero do resched again

CheckRunList:

    lis     r4, [hia]RunList            // Load address of run list
    addi    r4, r4, [lo]RunList         // ..
    lwz     r3, 4(r4)                   // Get pth from runlist
    cmpwi   r3, 0                       // if it's zero, we're idle
    bne     DoNewThread                 // Go get a new thread if there's one

Idle:
	mfmsr   r0							// Turn off interrupts
    MSR_CLR_EE(r0)
    mtmsr   r0
	
    bl      OEMIdle                     // Call OEM's idle routine

	mfmsr   r0							// Turn on interrupts
    ori     r0, r0, MSR_EE
    mtmsr   r0

    b       CheckResched                // Try reschedule path

DoNewThread:

    //
    // Scheduling new thread:
    //
    //  (r3) = RunList.pth
    //

    bl      SetCPUASID
    lis     r4, [hia]RunList            // Load address of run list
    addi    r4, r4, [lo]RunList         // ..
    lwz     r3, 4(r4)                   // Get pth from runlist
    lwz     r4, 0x3c(r3)                // get RunList.pth->hTh
    stw     r4, hCurThread(0)           // Store back current thread

    //
    // Ready to load our new thread.
    //
    // (r3) = RunList.pth
    //


    cmpwi   r14, 0
    beq-    LoadNewThread

    stw     r15, TcxR15(r14)    // save remaining general registers
    stw     r16, TcxR16(r14)    // ...
    stw     r17, TcxR17(r14)    // ...
    stw     r18, TcxR18(r14)    // ...
    stw     r19, TcxR19(r14)    // ...
    stw     r20, TcxR20(r14)    // ...
    stw     r21, TcxR21(r14)    // ...
    stw     r22, TcxR22(r14)    // ...
    stw     r23, TcxR23(r14)    // ...
    stw     r24, TcxR24(r14)    // ...
    stw     r25, TcxR25(r14)    // ...
    stw     r26, TcxR26(r14)    // ...
    stw     r27, TcxR27(r14)    // ...
    stw     r28, TcxR28(r14)    // ...
    stw     r29, TcxR29(r14)    // ...
    stw     r30, TcxR30(r14)    // ...
    stw     r31, TcxR31(r14)    // ...

LoadNewThread:

    mr      r14, r3             // (r14) = new Current Thread
    stw     r3, CurThdPtr(0)    // remember it for next interrupt

    lwz     r3, ThTlsPtr(r14)   // load the TLS pointer for the new thread
    stw     r3, lpvTls(0)       // set the KPage TLS Pointer

    lwz     r15, TcxR15(r14)    // reload non-volatile registers
    lwz     r16, TcxR16(r14)    // ...
    lwz     r17, TcxR17(r14)    // ...
    lwz     r18, TcxR18(r14)    // ...
    lwz     r19, TcxR19(r14)    // ...
    lwz     r20, TcxR20(r14)    // ...
    lwz     r21, TcxR21(r14)    // ...
    lwz     r22, TcxR22(r14)    // ...
    lwz     r23, TcxR23(r14)    // ...
    lwz     r24, TcxR24(r14)    // ...
    lwz     r25, TcxR25(r14)    // ...
    lwz     r26, TcxR26(r14)    // ...
    lwz     r27, TcxR27(r14)    // ...
    lwz     r28, TcxR28(r14)    // ...
    lwz     r29, TcxR29(r14)    // ...
    lwz     r30, TcxR30(r14)    // ...
    lwz     r31, TcxR31(r14)    // ...

ContinueCurThread:

    mfmsr   r0                  // Get current MSR
    MSR_CLR_EE(r0)              // Interrupts off
    MSR_CLR_RI(r0)              // Non-recoverable interrupts off
    mtmsr   r0                  // Update MSR
    isync
    lha     r3, ReschedFlag(0)
    li      r4, 0               // fake interrupt id for rescheduling
    cmpwi   r3, 1
    addi    r3, r3, 256
    beq-    Reschedule          // must reschedule
    sth     r3, ReschedFlag(0)

    //
    // Reload volatile register state.
    //

    lwz     r3, TcxLr(r14)
    lwz     r4, TcxCtr(r14)
    lwz     r5, TcxXer(r14)
    lwz     r6, TcxCr(r14)
    mtlr    r3                  // restore link register
    mtctr   r4                  // restore count register
    mtxer   r5                  // restore integer exception register
    mtcrf   0xff, r6            // restore condition register
    lwz     r3, TcxR3(r14)      // restore argument registers
    lwz     r4, TcxR4(r14)      // ...
    lwz     r5, TcxR5(r14)      // ...
    lwz     r6, TcxR6(r14)      // ...
    lwz     r7, TcxR7(r14)      // ...
    lwz     r8, TcxR8(r14)      // ...
    lwz     r9, TcxR9(r14)      // ...
    lwz     r10, TcxR10(r14)    // ...
    lwz     r0, TcxIar(r14)
    lwz     r11, TcxMsr(r14)
    lwz     r1, TcxR1(r14)
    lwz     r2, TcxR2(r14)
    mtspr   SRR0, r0            // set continuation address
    mtspr   SRR1, r11           // set continuation status register
    lwz     r0, TcxR0(r14)
    lwz     r11, TcxR11(r14)
    lwz     r12, TcxR12(r14)
    lwz     r13, TcxR13(r14)
    lwz     r14, TcxR14(r14)
    rfi

//
// END - KSEG Interrupt Handling Routines
//




    LEAF_ENTRY(INTERRUPTS_ON)
// INTERRUPTS_ON - enable external interrupts
//
//  Entry   none
//  Exit    none
//  Uses    r0
    mfmsr   r0
    ori     r0, r0, MSR_EE
    mtmsr   r0
    LEAF_EXIT(INTERRUPTS_ON)

    LEAF_ENTRY(INTERRUPTS_OFF)
// INTERRUPTS_OFF - disable external interrupts
//
//  Entry   none
//  Exit    none
//  Uses    r0
    mfmsr   r0
    MSR_CLR_EE(r0)
    mtmsr   r0
    LEAF_EXIT(INTERRUPTS_OFF)

PosTable:
    .byte 0,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
    .byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
    .byte 7,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
    .byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
    .byte 8,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
    .byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
    .byte 7,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
    .byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1

    LEAF_ENTRY(GetHighPos)

    lis     r4, [hia]PosTable
    addi    r4, r4, [lo]PosTable                // r4 == Ptr to PosTable

    subi    r5, r0, 1                           // r5 = offset to bit 0 of byte
    rlwinm  r6, r3, 0, 0xff                     // r6 = current byte of DWORD
    lbzx    r7, r4, r6                          // r7 = bit offset within byte
    cmpwi   r7, 0
    bne     res

    addi    r5, r5, 8                           // r5 == 7
    rlwinm  r6, r3, 24, 0xff
    lbzx    r7, r4, r6
    cmpwi   r7, 0
    bne     res

    addi    r5, r5, 8                           // r5 == 15
    rlwinm  r6, r3, 16, 0xff
    lbzx    r7, r4, r6
    cmpwi   r7, 0
    bne     res

    addi    r5, r5, 8                           // r5 == 23
    rlwinm  r6, r3, 8, 0xff
    lbzx    r7, r4, r6
    cmpwi   r7, 0
    bne     res
    li      r7, 9                               // set r7 so r5+r7=32  (r3==0)
res:
    add     r3, r5, r7
    blr
    LEAF_EXIT(GetHighPos)

    LEAF_ENTRY(ZeroPage)
//  void ZeroPage(void *vpPage)
//
//  Entry   (r3) = (vpPage) = ptr to address of page to zero
//  Return  none
//  Uses    r3, r4
//
//
    li      r4, PAGE_SIZE/32          // Number of loop iterations
    mtctr   r4                        //  stored to count register
    li      r4, 0

zp10:
    stw     r4, 0(r3)
    stw     r4, 4(r3)
    stw     r4, 8(r3)
    stw     r4, 12(r3)
    stw     r4, 16(r3)
    stw     r4, 20(r3)
    stw     r4, 24(r3)
    stw     r4, 28(r3)

    addi    r3, r3, 32                // Move pointer ahead
    bdnz+   zp10                      // Continue if not end of page

    LEAF_EXIT(ZeroPage)


    LEAF_ENTRY(InterlockedPopList)
// InterlockedPopList - remove first item from list
//
//  Entry   (r3) = ptr to list head
//  Return  (r3) = item at head of list
//      If (list not emtpy) next item is now head of list
//  Uses    r4, r5
    mr  r5, r3
ipop:
    lwarx   r4, 0, r5
    mr      r3, r4          // (r3) = ptr to item
    cmpwi   r4, 0
    beq-    ipopx
    lwz     r4, 0(r4)       // (r4) = ptr to next item
ipopx:
    stwcx.  r4, 0, r5       // update linkage & clear reservation
    bne-    ipop            // do it again, if stwcx. failed
    LEAF_EXIT(InterlockedPopList)

    LEAF_ENTRY(InterlockedPushList)
// InterlockedPushList - add an item to head of list
//
//  Entry   (r3) = ptr to list head
//          (r4) = ptr to item
//  Return  (r3) = old head of list
//  Uses    r0
ipsh:
    lwarx   r0, 0, r3       // (r0) = old list head
    stw     r0, 0(r4)       // store linkage
    stwcx.  r4, 0, r3       // store new list head
    bne-    ipsh            // do it again, if stwcx. failed
    mr      r3, r0
    LEAF_EXIT(InterlockedPushList)


    DUMMY_ENTRY(xKCall)
//++
// The following code is never executed. Its purpose is to support unwinding
// through the call to the exception dispatcher.
//--
    stw     r1,0(r1)        // save stack pointer
    stw     r31,4(r1)       // save linkage register
    mflr    r31             // save return address
    PROLOGUE_END(xKCall)

    ALTERNATE_ENTRY(KCall)
// KCall - call kernel function
//
// KCall invokes a kernel function in a non-preemtable state by incrementing
// the kernel nest level and switching onto a kernel stack.
//
// While in a preemtible state, the thread's register save area is
// volatile. On the way in, nothing can be saved into the thread
// structure until KNest is set and on the way out anything needed from the
// thread structure must be loaded before restoring KNest.
//
// The sequence of stack switching must be handled carefully because
// whenever KNest != 1, the general exception handler assumes that the kernel
// stack is current and will not switch stacks. On the way in, we must switch
// to the kernel stack before setting KNest but not use it until after KNest
// is set.  On the way out, we must reset KNest before restoring the thread's
// stack pointer.
//
//  Entry   (r3) = ptr to function to call
//          (r4) = first function arg
//          (r5) = second fucntion arg
//          (r6) = third function arg
//  Exit    (r3) = function return value
//  Uses    r0, r3-r12, ctr

    lha     r12, ReschedFlag(0)
    mtctr   r3                  // (r3) = ptr to function to call
    subic.  r12, r12, 256
    mr      r3, r4              // ripple args down
    mr      r4, r5
    mr      r5, r6
    bltctr-                     // nested kernel call, jump directly
                                //  to the function

// Entering non-preemptible state. We must switch onto the kernel stack
// before setting KNest in case an interrupt occurs during the switch.

    mr      r11, r1             // (r11) = original stack pointer
    li      r1, KStack          // switch to kernel stack
    stw     r12, ReschedFlag(0) // switch to non-preemtible state
    isync
    stw     r11, 0(r1)          // save original stack pointer
    stw     r31, 4(r1)          // save register for linkage
    mflr    r31
    bctrl                       // invoke non-preemptible function

// Function complete. Return to preemtible state after checking if a
//   reschedule is needed.

    lha     r10, ReschedFlag(0)
    cmpwi   r10, 1
    beq-    kc20

    lwz     r11, dwKCRes(0)
	cmpwi	r11, 1
	beq-	kc20

    mtlr    r31
    addi    r10, r10, 256
    lwz     r31, 4(r1)          // restore caller's R31
    lwz     r11, 0(r1)          // (r11) = caller's stack pointer
    sth     r10, ReschedFlag(0) // exit non-preemptible state
    mr      r1, r11             // restore the caller's stack pointer
    blr                         //  & return to caller

// ReschedFlag set, so must run the scheduler to find which thread
// to dispatch next.
//
//  (r3) = KCall return value
//  (r31) = return address

kc20:
    lwz     r11, CurThdPtr(0)   // (r11) = ptr to current thread
    mfmsr   r0                  // Current MSR is the one we want
    stw     r31, TcxIar(r11)    // thread resumes at return address
    stw     r0, TcxMsr(r11)     //   & in kernel mode.
    lwz     r0, 0(r1)           // (r0) = caller's R1 (stack pointer)
    stw     r2, TcxR2(r11)      // save Global pointer
    stw     r3, TcxR3(r11)      // save return value
    stw     r0, TcxR1(r11)      // save caller's stack pointer
    stw     r14, TcxR14(r11)
    lwz     r31, 4(r1)          // (r31) = caller's R31 value
    mr      r14, r11
    mfcr    r0
    stw     r0, TcxCr(r11)

    li      r4, ID_RESCHEDULE       // fake interrupt id for rescheduling

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -