/***************************************************************************
 * Copyright (c) 2024 Microsoft Corporation
 * Copyright (c) 2026-present Eclipse ThreadX contributors
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License which is available at
 * https://opensource.org/licenses/MIT.
 *
 * SPDX-License-Identifier: MIT
 **************************************************************************/


/**************************************************************************/
/**************************************************************************/
/**                                                                       */
/** ThreadX Component                                                     */
/**                                                                       */
/**   Thread                                                              */
/**                                                                       */
/**************************************************************************/
/**************************************************************************/


/* #define TX_SOURCE_CODE  */


/* Include necessary system files.  */

/*  #include "tx_api.h"
    #include "tx_thread.h"  */

    SECTION `.text`:CODE:REORDER:NOROOT(2)
    CODE
/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _tx_thread_stack_build                             RISC-V32/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    William E. Lamie, Microsoft Corporation                             */
/*    Tom van Leeuwen, Technolution B.V.                                  */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function builds a stack frame on the supplied thread's stack.  */
/*    The stack frame results in a fake interrupt return to the supplied  */
/*    function pointer.                                                   */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    thread_ptr                            Pointer to thread control blk */
/*    function_ptr                          Pointer to return function    */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _tx_thread_create                     Create thread service         */
/**************************************************************************/
/* VOID   _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
{  */
    PUBLIC  _tx_thread_stack_build
_tx_thread_stack_build:


    /* Build a fake interrupt frame.  The form of the fake interrupt stack
       on the RISC-V RV32 should look like the following after it is built:

       Stack Top:      1       (00)    Interrupt stack frame type
                       x27     (04)    Initial s11
                       x26     (08)    Initial s10
                       x25     (12)    Initial s9
                       x24     (16)    Initial s8
                       x23     (20)    Initial s7
                       x22     (24)    Initial s6
                       x21     (28)    Initial s5
                       x20     (32)    Initial s4
                       x19     (36)    Initial s3
                       x18     (40)    Initial s2
                       x9      (44)    Initial s1
                       x8      (48)    Initial s0
                       x31     (52)    Initial t6
                       x30     (56)    Initial t5
                       x29     (60)    Initial t4
                       x28     (64)    Initial t3
                       x7      (68)    Initial t2
                       x6      (72)    Initial t1
                       x5      (76)    Initial t0
                       x17     (80)    Initial a7
                       x16     (84)    Initial a6
                       x15     (88)    Initial a5
                       x14     (92)    Initial a4
                       x13     (96)    Initial a3
                       x12     (100)   Initial a2
                       x11     (104)   Initial a1
                       x10     (108)   Initial a0
                       x1      (112)   Initial ra
                       mepc    (120)   Initial mepc
If floating point support:
                       f0      (124)   Inital ft0
                       f1      (128)   Inital ft1
                       f2      (132)   Inital ft2
                       f3      (136)   Inital ft3
                       f4      (140)   Inital ft4
                       f5      (144)   Inital ft5
                       f6      (148)   Inital ft6
                       f7      (152)   Inital ft7
                       f8      (156)   Inital fs0
                       f9      (160)   Inital fs1
                       f10     (164)   Inital fa0
                       f11     (168)   Inital fa1
                       f12     (172)   Inital fa2
                       f13     (176)   Inital fa3
                       f14     (180)   Inital fa4
                       f15     (184)   Inital fa5
                       f16     (188)   Inital fa6
                       f17     (192)   Inital fa7
                       f18     (196)   Inital fs2
                       f19     (200)   Inital fs3
                       f20     (204)   Inital fs4
                       f21     (208)   Inital fs5
                       f22     (212)   Inital fs6
                       f23     (216)   Inital fs7
                       f24     (220)   Inital fs8
                       f25     (224)   Inital fs9
                       f26     (228)   Inital fs10
                       f27     (232)   Inital fs11
                       f28     (236)   Inital ft8
                       f29     (240)   Inital ft9
                       f30     (244)   Inital ft10
                       f31     (248)   Inital ft11
                       fscr    (252)   Inital fscr

    Stack Bottom: (higher memory address)  */

    lw      t0, 16(a0)                                  ; Pickup end of stack area
    li      t1, ~15                                     ; Build 16-byte alignment mask
    and     t0, t0, t1                                  ; Make sure 16-byte alignment

    /* Actually build the stack frame.  */

#if __iar_riscv_base_isa == rv32e
    addi    t0, t0, -260
#else
    addi    t0, t0, -128                                ; Allocate space for the stack frame
#endif
    li      t1, 1                                       ; Build stack type
    sw      t1, 0(t0)                                   ; Place stack type on the top
    sw      x0, 4(t0)                                   ; Initial s11
    sw      x0, 8(t0)                                   ; Initial s10
    sw      x0, 12(t0)                                  ; Initial s9
    sw      x0, 16(t0)                                  ; Initial s8
    sw      x0, 20(t0)                                  ; Initial s7
    sw      x0, 24(t0)                                  ; Initial s6
    sw      x0, 28(t0)                                  ; Initial s5
    sw      x0, 32(t0)                                  ; Initial s4
    sw      x0, 36(t0)                                  ; Initial s3
    sw      x0, 40(t0)                                  ; Initial s2
    sw      x0, 44(t0)                                  ; Initial s1
    sw      x0, 48(t0)                                  ; Initial s0
    sw      x0, 52(t0)                                  ; Initial t6
    sw      x0, 56(t0)                                  ; Initial t5
    sw      x0, 60(t0)                                  ; Initial t4
    sw      x0, 64(t0)                                  ; Initial t3
    sw      x0, 68(t0)                                  ; Initial t2
    sw      x0, 72(t0)                                  ; Initial t1
    sw      x0, 76(t0)                                  ; Initial t0
    sw      x0, 80(t0)                                  ; Initial a7
    sw      x0, 84(t0)                                  ; Initial a6
    sw      x0, 88(t0)                                  ; Initial a5
    sw      x0, 92(t0)                                  ; Initial a4
    sw      x0, 96(t0)                                  ; Initial a3
    sw      x0, 100(t0)                                 ; Initial a2
    sw      x0, 104(t0)                                 ; Initial a1
    sw      x0, 108(t0)                                 ; Initial a0
    sw      x0, 112(t0)                                 ; Initial ra
    sw      a1, 120(t0)                                 ; Initial mepc
#if __iar_riscv_base_isa == rv32e
    sw      x0, 124(t0)                                 ; Inital ft0
    sw      x0, 128(t0)                                 ; Inital ft1
    sw      x0, 132(t0)                                 ; Inital ft2
    sw      x0, 136(t0)                                 ; Inital ft3
    sw      x0, 140(t0)                                 ; Inital ft4
    sw      x0, 144(t0)                                 ; Inital ft5
    sw      x0, 148(t0)                                 ; Inital ft6
    sw      x0, 152(t0)                                 ; Inital ft7
    sw      x0, 156(t0)                                 ; Inital fs0
    sw      x0, 160(t0)                                 ; Inital fs1
    sw      x0, 164(t0)                                 ; Inital fa0
    sw      x0, 168(t0)                                 ; Inital fa1
    sw      x0, 172(t0)                                 ; Inital fa2
    sw      x0, 176(t0)                                 ; Inital fa3
    sw      x0, 180(t0)                                 ; Inital fa4
    sw      x0, 184(t0)                                 ; Inital fa5
    sw      x0, 188(t0)                                 ; Inital fa6
    sw      x0, 192(t0)                                 ; Inital fa7
    sw      x0, 196(t0)                                 ; Inital fs2
    sw      x0, 200(t0)                                 ; Inital fs3
    sw      x0, 204(t0)                                 ; Inital fs4
    sw      x0, 208(t0)                                 ; Inital fs5
    sw      x0, 212(t0)                                 ; Inital fs6
    sw      x0, 216(t0)                                 ; Inital fs7
    sw      x0, 220(t0)                                 ; Inital fs8
    sw      x0, 224(t0)                                 ; Inital fs9
    sw      x0, 228(t0)                                 ; Inital fs10
    sw      x0, 232(t0)                                 ; Inital fs11
    sw      x0, 236(t0)                                 ; Inital ft8
    sw      x0, 240(t0)                                 ; Inital ft9
    sw      x0, 244(t0)                                 ; Inital ft10
    sw      x0, 248(t0)                                 ; Inital ft11
    csrr    a1, fcsr                                    ; Read fcsr and use it for initial value for each thread
    sw      a1, 252(t0)                                 ; Initial fscr
    sw      x0, 256(t0)                                 ; Reserved word (0)
#else
    sw      x0, 124(t0)                                 ; Reserved word (0)
#endif

    /* Setup stack pointer.  */
    /* thread_ptr -> tx_thread_stack_ptr =  t0;  */

    sw      t0, 8(a0)                                   ; Save stack pointer in thread's
    ret                                                 ;   control block and return
/* }  */
    END

