.data


.text

//Save return label address for the coreLoop to pointer
//Arguments: Pointer to variable holding address
.globl saveCoreLoopReturnAddr
saveCoreLoopReturnAddr:
    movq    $coreLoopReturn, %rcx   #load label address
    movq    %rcx, (%rdi)           #save address to pointer
    ret


//Initializes VirtProcrFn at first run for 64 bit mode
//Puts argument from stack into registers
.globl startVirtProcrFn
startVirtProcrFn:
    movq    %rdi      , %rsi #get second argument from first argument of switchVP
    movq    0x08(%rsp), %rdi #get first argument
    movq    (%rsp)    , %rax #get function addr
    jmp     *%rax

//Switches form CoreLoop to VP ether a normal VP or the Master Loop
//switch to virt procr's stack and frame ptr then jump to virt procr fn
/* VirtProcr  offsets:
 * 0x10  stackPtr
 * 0x18 framePtr
 * 0x20 nextInstrPt
 * 0x30 coreLoopFramePtr
 * 0x38 coreLoopStackPtr
 *
 * _VMSMasterEnv  offsets:
 * 0x48 coreLoopReturnPt
 * 0x54 masterLock
 */
.globl switchToVP
switchToVP:
    #VirtProcr in %rdi
    movq    %rsp      , 0x38(%rdi)   #save core loop stack pointer 
    movq    %rbp      , 0x30(%rdi)   #save core loop frame pointer
    movq    0x10(%rdi), %rsp         #restore stack pointer
    movq    0x18(%rdi), %rbp         #restore frame pointer
    movq    0x20(%rdi), %rax         #get jmp pointer
    jmp     *%rax                    #jmp to VP
coreLoopReturn:
    ret

    
//switches to core loop. saves return address
/* VirtProcr  offsets:
 * 0x10  stackPtr
 * 0x18 framePtr
 * 0x20 nextInstrPt
 * 0x30 coreLoopFramePtr
 * 0x38 coreLoopStackPtr
 *
 * _VMSMasterEnv  offsets:
 * 0x48 coreLoopReturnPt
 * 0x54 masterLock
 */
.globl switchToCoreLoop
switchToCoreLoop:
    #VirtProcr in %rdi
    movq    $VPReturn , 0x20(%rdi)   #store return address
    movq    %rsp      , 0x10(%rdi)   #save stack pointer 
    movq    %rbp      , 0x18(%rdi)   #save frame pointer
    movq    0x38(%rdi), %rsp         #restore stack pointer
    movq    0x30(%rdi), %rbp         #restore frame pointer
    movq    $_VMSMasterEnv, %rcx
    movq    (%rcx)    , %rcx
    movq    0x48(%rcx), %rax         #get CoreLoopStartPt
    jmp     *%rax                    #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:
 * 0x10  stackPtr
 * 0x18 framePtr
 * 0x20 nextInstrPt
 * 0x30 coreLoopFramePtr
 * 0x38 coreLoopStackPtr
 *
 * _VMSMasterEnv  offsets:
 * 0x48 coreLoopReturnPt
 * 0x54 masterLock
 */
.globl masterSwitchToCoreLoop
masterSwitchToCoreLoop:
    #VirtProcr in %rdi
    movq    $MasterReturn, 0x20(%rdi)   #store return address
    movq    %rsp      , 0x10(%rdi)   #save stack pointer 
    movq    %rbp      , 0x18(%rdi)   #save frame pointer
    movq    0x38(%rdi), %rsp         #restore stack pointer
    movq    0x30(%rdi), %rbp         #restore frame pointer
    movq    $_VMSMasterEnv, %rcx
    movq    (%rcx)    , %rcx
    movq    0x48(%rcx), %rax         #get CoreLoopStartPt
    movl    $0x0      , 0x54(%rcx)   #release lock
    jmp     *%rax                    #jmp to CoreLoop
MasterReturn:
    ret


//Switch to terminateCoreLoop
//therefor switch to coreLoop context from master context
// no need to call because the stack is already set up for switchVP
// and virtPr is in %rdi
// and both functions have the same argument.
// do not save register of VP because this function will never return
/* VirtProcr  offsets:
 * 0x10  stackPtr
 * 0x18 framePtr
 * 0x20 nextInstrPt
 * 0x30 coreLoopFramePtr
 * 0x38 coreLoopStackPtr
 *
 * _VMSMasterEnv  offsets:
 * 0x48 coreLoopReturnPt
 * 0x58 masterLock
 */
.globl asmTerminateCoreLoop
asmTerminateCoreLoop:
    #VirtProcr in %rdi
    movq    0x38(%rdi), %rsp         #restore stack pointer
    movq    0x30(%rdi), %rbp         #restore frame pointer
    movq    $terminateCoreLoop, %rax
    jmp     *%rax                    #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:
    #VirtProcr in %rdi
    movq    0x38(%rdi), %rsp         #restore stack pointer
    movq    0x30(%rdi), %rbp         #restore frame pointer
    #argument is in %rdi
    call    VMS__dissipate_procr
    movq    %rbp      , %rsp        #goto the coreLoops stack
    pop     %rbp        #restore the old framepointer
    ret                 #return from core loop
    
