.data


.text

//Save return label address for the coreLoop to pointer
//Arguments: Pointer to variable holding address
.globl saveCoreLoopReturnAddr
saveCoreLoopReturnAddr:
    movl    0x4(%esp) , %eax       #load pointer
    movl    $coreLoopReturn, %ecx   #load label address
    movl    %ecx, (%eax)           #save address
    ret



//Switches form CoreLoop to VP ether normal VP or the Master Loop
//switch to virt procr's stack and frame ptr then jump to virt procr fn
/* VirtProcr  offsets:
 * 0xc  stackPtr
 * 0x10 framePtr
 * 0x14 nextInstrPt
 * 0x1c coreLoopFramePtr
 * 0x20 coreLoopStackPtr
 *
 * _VMSMasterEnv  offsets:
 * 0x24 coreLoopReturnPt
 * 0x2c masterLock
 */
.globl switchToVP
switchToVP:
    movl    0x4(%esp) , %ecx         #get VirtProcr
    movl    %esp      , 0x20(%ecx)   #save core loop stack pointer 
    movl    %ebp      , 0x1c(%ecx)   #save core loop frame pointer
    movl    0x0c(%ecx), %esp         #restore stack pointer
    movl    0x10(%ecx), %ebp         #restore frame pointer
    movl    0x14(%ecx), %eax         #get jmp pointer
    jmp     *%eax                    #jmp to VP
coreLoopReturn:
    ret

    
//switches to core loop. saves return address
/* VirtProcr  offsets:
 * 0xc  stackPtr
 * 0x10 framePtr
 * 0x14 nextInstrPt
 * 0x1c coreLoopFramePtr
 * 0x20 coreLoopStackPtr
 *
 * _VMSMasterEnv  offsets:
 * 0x24 coreLoopReturnPt
 * 0x28 coreLoopEndPt
 * 0x2c masterLock
 */
.globl switchToCoreLoop
switchToCoreLoop:
    movl    0x4(%esp) , %ecx         #get VirtProcr
    movl    $VPReturn , 0x14(%ecx)   #store return address
    movl    %esp      , 0x0c(%ecx)   #save stack pointer 
    movl    %ebp      , 0x10(%ecx)   #save frame pointer
    movl    0x20(%ecx), %esp         #restore stack pointer
    movl    0x1c(%ecx), %ebp         #restore frame pointer
    movl    $_VMSMasterEnv, %ecx
    movl    (%ecx)    , %ecx
    movl    0x24(%ecx), %eax         #get CoreLoopStartPt
    jmp     *%eax                    #jmp to CoreLoop
VPReturn:
    ret



//switches to core loop from master. saves return address
//Releases masterLock so the next MasterLoop can be executed
/* VirtProcr  offsets:
 * 0xc  stackPtr
 * 0x10 framePtr
 * 0x14 nextInstrPt
 * 0x1c coreLoopFramePtr
 * 0x20 coreLoopStackPtr
 *
 * _VMSMasterEnv  offsets:
 * 0x24 coreLoopReturnPt
 * 0x2c masterLock
 */
.globl masterSwitchToCoreLoop
masterSwitchToCoreLoop:
    movl    0x4(%esp) , %ecx         #get VirtProcr
    movl    $MasterReturn, 0x14(%ecx)   #store return address
    movl    %esp      , 0x0c(%ecx)   #save stack pointer 
    movl    %ebp      , 0x10(%ecx)   #save frame pointer
    movl    0x20(%ecx), %esp         #restore stack pointer
    movl    0x1c(%ecx), %ebp         #restore frame pointer
    movl    $_VMSMasterEnv, %ecx
    movl    (%ecx)    , %ecx
    movl    0x24(%ecx), %eax         #get CoreLoopStartPt
    movl    $0x0      , 0x2c(%ecx)   #release lock
    jmp     *%eax                    #jmp to CoreLoop
MasterReturn:
    ret


//Switch to terminateCoreLoop
// no need to call because the stack is already set up for switchVP
// and both functions have the same argument.
// do not save register of VP because this function will never return
/* VirtProcr  offsets:
 * 0xc  stackPtr
 * 0x10 framePtr
 * 0x14 nextInstrPt
 * 0x1c coreLoopFramePtr
 * 0x20 coreLoopStackPtr
 *
 * _VMSMasterEnv  offsets:
 * 0x24 coreLoopReturnPt
 * 0x2c masterLock
 */
.globl asmTerminateCoreLoop
asmTerminateCoreLoop:
    movl    0x4(%esp) , %ecx         #get VirtProcr
    movl    0x20(%ecx), %esp         #restore stack pointer
    movl    0x1c(%ecx), %ebp         #restore frame pointer
    movl    $terminateCoreLoop, %eax
    jmp     *%eax                    #jmp to CoreLoop


/*
 * This one for the sequential version is special. It discards the current stack
 * and returns directly from the coreLoop after VMS__dissipate_procr was called
 */
.globl asmTerminateCoreLoopSeq
asmTerminateCoreLoopSeq:
    movl    0x4(%esp) , %ecx         #get VirtProcr
    movl    0x20(%ecx), %esp         #restore stack pointer
    movl    0x1c(%ecx), %ebp         #restore frame pointer
    sub     $0x4      , %esp
    movl    %ecx      , (%esp)       #put argument on stack
    call    VMS__dissipate_procr
    movl    %ebp      , %esp        #goto the coreLoops stack
    pop     %ebp        #restore the old framepointer
    ret                 #return from core loop
    
