/*
    SyscallMsg.S, Copyright (c) by Silvio Dragone & David Reist,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.

    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.

    For further information, please visit http://www.tik.ee.ethz.ch/~topsy

    This software is provided under the terms of the GNU General Public Licence.

    A full copy of the GNU GPL is provided in the file COPYING found in the 
    development root of Topsy.
*/
/*
	
    File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/Topsy/sa1100/SyscallMsg.S,v $
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2894 $
    Last Date of Change:   $Date: 2006-11-28 16:36:06 +0100 (Die, 28 Nov 2006) $  by: $Author: rnatau $

*/
	  
#include "asm.h"
#include "SyscallMsg.h"

.text
	
.equ SYSCALL_SEND_OP,      dSYSCALL_SEND_OP
.equ SYSCALL_RECV_OP,      dSYSCALL_RECV_OP
.equ MESSAGEFROM_OFFSET,   0x0
.equ syscall,              0x00000001

    /* Basic mechanismus for sending messages (SWI exception),
     * Argument registers are:
     *     a0: destination thread (ThreadId)
     *     a1: message reference (Message *msg)
     */
ENTRY(tmMsgSend)
	mov	ip, sp
	stmdb	sp!, {fp, ip, lr, pc}
	sub	fp, ip, #4
	str	a0, [a1]	// dest. thread put into msg from field
	mov	a3, #SYSCALL_SEND_OP
    
	/* Argument registers are now:
	    a0: - (undefined)
	    a1: message reference (Message*) (destination thread id included)
	    a2: - (undefined)
	    a3: SYSCALL_SEND_OP
	*/
	
	swi	#syscall	// Raising of an swi exception

	/* The return value of tmMsgSend() is in a0 is it was stored 
	 * the senders context in msgDispatcher 
	 */
	ldmdb	fp, {fp, sp, pc}


    /* Basic mechanismus for receiving messages (SWI exception),
     *	Argument registers are:
     *	    a0: expected thread id (ThreadId*)
     *	    a1: expected message type (MessageId)
     *	    a2: message reference (Message*)
     *	    a3: timeout (int milliseconds)
     */
ENTRY(tmMsgRecv)
	mov	ip, sp
	stmdb	sp!, {a0, v0, fp, ip, lr, pc} // preserve all the local registers
	sub	fp, ip, #4
	ldr	v0, [a0]	// dereference a0 -> v0
	str	v0, [a2]	// threadId (v0) copied into from field
	str	a1, [a2, #4]	// msgId (a1) copied into id field of msg
	mov	a1, a2		// shifting of arguments
	mov	a2, a3		// shifting of arguments
	mov	a3, #SYSCALL_RECV_OP

        /* Argument registers are now:
              a0: - (undefined) (actually unchanged)
              a1: message reference (Message*)
              a2: timeout (unsigned long int)
              a3: SYSCALL_RECV_OP
        */

	swi	#syscall	// Raising of an swi exception

	/* from field of tmMsgRecv() is set with msgPtr->from */
	ldr	ip, [sp]	// get the thread id out of the stack
	ldr	v0, [a1, #MESSAGEFROM_OFFSET]
	str	v0, [ip]
	
       /* The return value of tmMsgRecv() is in a0 */
	ldmdb	fp, {v0, fp, sp, pc} // DON'T RESTORE A0!!!
