/*
 * hal_user_syscall.c - Implementation of user-side HAL API for TSAR-MIPS32.
 * 
 * Author    Alain Greiner (2016,2017)
 *
 * 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
 */


/////////////////////////////////////////////
inline int hal_user_syscall( int service_num,
                             int arg0,
                             int arg1,
                             int arg2,
                             int arg3 )
{
    register int reg_num_and_ret __asm__("v0") = service_num;
    register int reg_a0          __asm__("a0") = arg0;
    register int reg_a1          __asm__("a1") = arg1;
    register int reg_a2          __asm__("a2") = arg2;
    register int reg_a3          __asm__("a3") = arg3;

    __asm__ volatile(
            "syscall"
            : "+r" (reg_num_and_ret),
              "+r" (reg_a0),             
              "+r" (reg_a1),
              "+r" (reg_a2),
              "+r" (reg_a3)
            : 
            : "memory",
              "at",
              "v1",
              "ra",
              "t0",
              "t1",
              "t2",
              "t3",
              "t4",
              "t5",
              "t6",
              "t7",
              "t8",
              "t9"
               );

    return (volatile int)reg_num_and_ret;
}

///////////////////////////////////
int hal_user_atomic_add( int * ptr,
                         int   val )
{
	int current;
 
	asm volatile (
		 ".set noreorder		             \n"	
		 "1:                                 \n"
		 "ll      %0,      (%1)              \n"
		 "addu    $3,      %0,       %2      \n"
		 "sc      $3,      (%1)              \n"
		 "beq     $3,      $0,       1b      \n"
		 "nop                                \n"
		 "sync                               \n"
		 ".set reorder			             \n"	
		 :"=&r"(current) : "r" (ptr), "r" (val) : "$3" , "memory" );

	return current;
}

/////////////////////
void hal_user_fence()
{
	asm volatile ( "sync" );
}
