/*
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * https://www.FreeRTOS.org
 * https://github.com/FreeRTOS
 *
 */

.file "portASM.S"
#include "FreeRTOSConfig.h"
#include "ISR_Support.h"

    .extern pxCurrentTCB
    .extern vTaskSwitchContext
    .extern vPortCentralInterruptHandler
    .extern xTaskIncrementTick
    .extern vPortAPICErrorHandler
    .extern pucPortTaskFPUContextBuffer
    .extern ulPortYieldPending

    .global vPortStartFirstTask
    .global vPortCentralInterruptWrapper
    .global vPortAPICErrorHandlerWrapper
    .global vPortTimerHandler
    .global vPortYieldCall
    .global vPortAPICSpuriousHandler

    .text

/*-----------------------------------------------------------*/

.align 4
.func vPortYieldCall
vPortYieldCall:
    /* Save general purpose registers. */
    pusha

    .if configSUPPORT_FPU == 1

        /* If the task has a buffer allocated to save the FPU context then save
        the FPU context now. */
        movl    pucPortTaskFPUContextBuffer, %eax
        test    %eax, %eax
        je      1f
        fnsave  ( %eax )
        fwait

        1:

        /* Save the address of the FPU context, if any. */
        push    pucPortTaskFPUContextBuffer

    .endif /* configSUPPORT_FPU */

    /* Find the TCB. */
    movl    pxCurrentTCB, %eax

    /* Stack location is first item in the TCB. */
    movl    %esp, (%eax)

    call vTaskSwitchContext

    /* Find the location of pxCurrentTCB again - a callee saved register could
    be used in place of eax to prevent this second load, but that then relies
    on the compiler and other asm code. */
    movl    pxCurrentTCB, %eax
    movl    (%eax), %esp

    .if configSUPPORT_FPU == 1

        /* Restore address of task's FPU context buffer. */
        pop     pucPortTaskFPUContextBuffer

        /* If the task has a buffer allocated in which its FPU context is saved,
        then restore it now. */
        movl    pucPortTaskFPUContextBuffer, %eax
        test    %eax, %eax
        je      1f
        frstor  ( %eax )
        1:
    .endif

    popa
    iret

.endfunc
/*-----------------------------------------------------------*/

.align 4
.func vPortStartFirstTask
vPortStartFirstTask:

    /* Find the TCB. */
    movl    pxCurrentTCB, %eax

    /* Stack location is first item in the TCB. */
    movl    (%eax), %esp

    /* Restore FPU context flag. */
    .if configSUPPORT_FPU == 1

        pop     pucPortTaskFPUContextBuffer

    .endif /* configSUPPORT_FPU */

    /* Restore general purpose registers. */
    popa
    iret
.endfunc
/*-----------------------------------------------------------*/

.align 4
.func vPortAPICErrorHandlerWrapper
vPortAPICErrorHandlerWrapper:
    pusha
    call    vPortAPICErrorHandler
    popa
    /* EOI. */
    movl    $0x00, (0xFEE000B0)
    iret
.endfunc
/*-----------------------------------------------------------*/

.align 4
.func vPortTimerHandler
vPortTimerHandler:

    /* Save general purpose registers. */
    pusha

    /* Interrupts are not nested, so save the rest of the task context. */
    .if configSUPPORT_FPU == 1

        /* If the task has a buffer allocated to save the FPU context then save the
        FPU context now. */
        movl    pucPortTaskFPUContextBuffer, %eax
        test    %eax, %eax
        je      1f
        fnsave  ( %eax ) /* Save FLOP context into ucTempFPUBuffer array. */
        fwait

        1:
        /* Save the address of the FPU context, if any. */
        push    pucPortTaskFPUContextBuffer

    .endif /* configSUPPORT_FPU */

    /* Find the TCB. */
    movl    pxCurrentTCB, %eax

    /* Stack location is first item in the TCB. */
    movl    %esp, (%eax)

    /* Switch stacks. */
    movl    ulTopOfSystemStack, %esp
    movl    %esp, %ebp

    /* Increment nesting count. */
    add     $1, ulInterruptNesting

    call    xTaskIncrementTick

    sti

    /* Is a switch to another task required? */
    test    %eax, %eax
    je      _skip_context_switch
    cli
    call    vTaskSwitchContext

_skip_context_switch:
    cli

    /* Decrement the variable used to determine if a switch to a system
    stack is necessary. */
    sub     $1, ulInterruptNesting

    /* Stack location is first item in the TCB. */
    movl    pxCurrentTCB, %eax
    movl    (%eax), %esp

    .if configSUPPORT_FPU == 1

        /* Restore address of task's FPU context buffer. */
        pop     pucPortTaskFPUContextBuffer

        /* If the task has a buffer allocated in which its FPU context is saved,
        then restore it now. */
        movl    pucPortTaskFPUContextBuffer, %eax
        test    %eax, %eax
        je      1f
        frstor  ( %eax )
        1:
    .endif

    popa

    /* EOI. */
    movl    $0x00, (0xFEE000B0)
    iret

.endfunc
/*-----------------------------------------------------------*/

.if configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1

    .align 4
    .func vPortCentralInterruptWrapper
    vPortCentralInterruptWrapper:

        portFREERTOS_INTERRUPT_ENTRY

        movl $0xFEE00170, %eax          /* Highest In Service Register (ISR) long word. */
        movl $8, %ecx                   /* Loop counter. */

    next_isr_long_word:
        test %ecx, %ecx                 /* Loop counter reached 0? */
        je wrapper_epilogue             /* Looked at all ISR registers without finding a bit set. */
        sub $1, %ecx                    /* Sub 1 from loop counter. */
        movl (%eax), %ebx               /* Load next ISR long word. */
        sub $0x10, %eax                 /* Point to next ISR long word in case no bits are set in the current long word. */
        test %ebx, %ebx                 /* Are there any bits set? */
        je next_isr_long_word           /* Look at next ISR long word if no bits were set. */
        sti
        bsr %ebx, %ebx                  /* A bit was set, which one? */
        movl $32, %eax                  /* Destination operand for following multiplication. */
        mul %ecx                        /* Calculate base vector for current register, 32 vectors per register. */
        add %ebx, %eax                  /* Add bit offset into register to get final vector number. */
        push %eax                       /* Vector number is function parameter. */
        call vPortCentralInterruptHandler
        pop %eax                        /* Remove parameter. */

    wrapper_epilogue:
        portFREERTOS_INTERRUPT_EXIT

    .endfunc

.endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
/*-----------------------------------------------------------*/

.align 4
.func vPortAPISpuriousHandler
vPortAPICSpuriousHandler:
    iret

.endfunc

.end
