/*
 * boot_entry.S - TSAR bootloader entry point.
 * 
 * Authors :   Alain Greiner / Vu Son  (2016)
 *
 * Copyright (c) UPMC Sorbonne Universites
 *
 * This file is part of ALMOS-MKH.
 *
 * ALMOS-MKH is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2.0 of the License.
 *
 * ALMOS-MKH is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

/**********************************************************************************************
 * This file contains the entry point of the ALMOS-MK boot-loader for TSAR architecture,      *
 * that is a generic multi-clusters / multi-processors architecture.                          *
 *                                                                                            *
 * - The number of clusters is defined by the (X_SIZE, Y_SIZE) parameters in the              *
 *   hard_config.h file (up to 256 clusters).                                                 *
 * - The number of processors per cluster is defined by the NB_PROCS_MAX parameter in the     *
 *   hard_config.h file (up to 4 processors per cluster).                                     *
 *                                                                                            *
 * This assembly code is executed by all cores, but at the same time, because all cores       *
 * are not simultaneously activated. It makes the assuption that the CPO register containing  *
 * the core gid (global hardware identifier) has a fixed format:                              *
 *    gid == (((x << Y_WIDTH) + y) << P_WIDTH) + lid                                          *
 *                                                                                            *
 * It does 3 things:                                                                          *
 * - It initializes the stack pointer depending on the lid extracted from the gid,            *
 *   using the BOOT_STACK_BASE and BOOT_STACK_SIZE parameters defined in the                  *
 *   'boot_config.h' file,                                                                    *
 * - It changes the value of the DATA address extension register using the cxy extracted      *
 *   from the gid,                                                                            *
 * - It jumps to the boot_loader() function defined in the 'boot.c' file, passing the two     *
 *   arguments (cxy and lid).                                                                 *
 *********************************************************************************************/

#include "mips32_registers.h"
#include "hard_config.h"
#include "boot_config.h"

    .section    .text, "ax", @progbits

    .globl      boot_entry
    .ent        boot_entry

    .align      2
    .set        noreorder

boot_entry:

    /* Get (cxy, lid) values from gid contained in CP0 register  */

    mfc0    k0,     CP0_PROCID          
    andi    k0,     k0,     0xFFF                       /* k0 <= gid                        */
    andi    t1,     k0,     ((1 << P_WIDTH) - 1)        /* t1 <= lid                        */
    srl     t2,     k0,     P_WIDTH                     /* t2 <= cxy                        */
    
    /* Initialize stack pointer from lid value  */
    
    la      t0,     BOOT_STACK_BASE                     /* t0 <= BOOT_STACK_BASE            */
    li      k1,     BOOT_STACK_SIZE                     /* k1 <= BOOT_STACK_SIZE            */
    multu   k1,     t1
    mflo    k0                                          /* k0 <= BOOT_STACK_SIZE * lid      */
    subu    sp,     t0,     k0                          /* P[cxy,lid] sp initialized        */ 

    /* Switch to local DSPACE by changing the value of the address extension register       */

    mtc2    t2,     CP2_DATA_PADDR_EXT

    /* Jump to boot_loader() function after passing (cxy,lid) arguments in the registers    */

    or      a0,     zero,   t1                          /* a0 <= lid                        */     
    or      a1,     zero,   t2                          /* a1 <= cxy                        */
    la      ra,     boot_loader
    jr      ra
    nop

    .end boot_entry

    .set reorder
