/*
    SyscallMsg.S, Copyright  (c) by Lukas Ruf, lr@lpr.ch,
    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/ia32/SyscallMsg.S,v $
 	Author(s):             Lukas Ruf, lr@lpr.ch
 	Affiliation:           ETH Zuerich, TIK
 	Version:               $Revision: 3016 $
 	Creation Date:         
 	Last Date of Change:   $Date: 2007-04-27 20:10:03 +0200 (Fre, 27 Apr 2007) $      by: $Author: sryffel $
*/

#include "asm.h"

#include "SyscallMsg.h"


    .section .sasm
    .align 4,0x9090

    /* Basic mechanismus for sending messages (SYSCALL exception),
     * Argument registers are:
     *            eax : SYSCALL_SEND_OP
     *   ARG1 --  ebx : Thread ID where message should be sent to
     *   ARG2 --  esi : message reference (Message *msg)
     * i386 specialities:
     *  tmMsgSend() unpacks the arguments from stack to registers and 
     *  launches a SYSCALL :-) {Software Interrupt 0x30}
     *
     * tmMsgSend(ThreadID pID, Message *pMSG);
     */

  ASM_PROC_FRAME(tmMsgSend)
        ENTER           /* Thread Stack */
        
        /* Do not save eax: the result will be passed via eax */
        pushl   %ebx                    /* save as they will be modified */
        pushl   %esi

        movl    $dSYSCALL_SEND_OP,%eax  /* Type of Syscall */
        
        movl    ARG1,%ebx               /* Thread ID of the receiver */
        movl    ARG2,%esi               /* Message Reference */

        /* NOTE: Thread IDs of Sender (from) and Receiver (to) are temporarely
           exchanged (in msgDispatcher they are restored). This was not funny :-(
         */
        xchgl   %ebx,0(%esi) 
    
        SYSCALL                         /* :-) */

        popl    %esi                    /* Restore ebx,esi: not used for results passing */
        popl    %ebx
        
        LEAVE                           /* Back on User Stack */



    /* Basic mechanismus for receiving messages (SYSCALL exception),
        Argument registers are:
             eax: SYSCALL_RECV_OP
        ARG1 ebx: Thread ID
        ARG3 esi: message reference (Message*)
        ARG2 ecx: expected message type (MessageId)
        ARG4 edx: timeout (int milliseconds)
        
        tmMsgRecv(ThreadID *from, MessageID ID, Message *msg, int timeout);
    */
  ASM_PROC_FRAME(tmMsgRecv)
        ENTER
        
        
        pushl   %ebx
        pushl   %ecx
        pushl   %edx
        pushl   %edi
        pushl   %esi
        
        movl    ARG1,%edi       /* from         */
        movl    (%edi),%ebx     /* dereference expected ThreadID */
        movl    ARG2,%ecx       /* msgID        */ 
        movl    ARG3,%esi       /* msg          */
        movl    ARG4,%edx       /* timeOut      */

        movl    %ebx,0(%esi)    /* save expected ThreadID in msg.from */
        movl    %ecx,4(%esi)    /* save "expected Message ID" */
    
        movl    $dSYSCALL_RECV_OP,%eax

        SYSCALL         /* :-) : Software Interrupt 0x30 */

        /* BACK ON USER STACK */
        
        popl    %esi    
        popl    %edi    
        popl    %edx    /* Restore general purpose registers from user stack */ 
        popl    %ecx    
        popl    %ebx    

        
        LEAVE


