| Index: src/trusted/service_runtime/arch/mips/nacl_syscall.S
 | 
| diff --git a/src/trusted/service_runtime/arch/mips/nacl_syscall.S b/src/trusted/service_runtime/arch/mips/nacl_syscall.S
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..4a6f40f411360188f25e68c1e612e01de3a2dc88
 | 
| --- /dev/null
 | 
| +++ b/src/trusted/service_runtime/arch/mips/nacl_syscall.S
 | 
| @@ -0,0 +1,131 @@
 | 
| +/*
 | 
| + * Copyright 2012 The Native Client Authors.  All rights reserved.
 | 
| + * Use of this source code is governed by a BSD-style license that can
 | 
| + * be found in the LICENSE file.
 | 
| + */
 | 
| +
 | 
| +#include "native_client/src/trusted/service_runtime/arch/mips/sel_rt.h"
 | 
| +#include "native_client/src/trusted/service_runtime/nacl_config.h"
 | 
| +
 | 
| +.text
 | 
| +
 | 
| +
 | 
| +/*
 | 
| + * This trusted code is linked into the service runtime. It is executed when a
 | 
| + * nacl module performs a system call via a service runtime interface. The nacl
 | 
| + * module jumps to the trampoline corresponding to the syscall and then here.
 | 
| + * This code switches the execution contexts (registers and stack) from
 | 
| + * untrusted to trusted.
 | 
| + *
 | 
| + * on stack:
 | 
| + *
 | 
| + * top
 | 
| + * =====
 | 
| + * a0 - alignment for NaClSyscallCSegHook
 | 
| + * ra - return address
 | 
| + * arg 1
 | 
| + * arg 2
 | 
| + * .....
 | 
| + * arg N
 | 
| + */
 | 
| +
 | 
| +DEFINE_GLOBAL_HIDDEN_IDENTIFIER(NaClSyscallSeg):
 | 
| +
 | 
| +  .set noreorder
 | 
| +
 | 
| +/*
 | 
| + * The following code (next 6 instructions) does what the trampoline code should
 | 
| + * do. It places the first 4 parameters of the system call to the stack, and on
 | 
| + * top of that it places the return address to the user module. On Mips the
 | 
| + * trampoline is too small for all this, so the code is moved here.
 | 
| + *
 | 
| + * Mips passes parameters to a callee in registers a0-a3. If there are more
 | 
| + * than 4 parameters, the first four args are passed in registers and the rest
 | 
| + * are placed on the stack. Regardless of the number of arguments passed, Mips
 | 
| + * o32 ABI requires that the caller should always reserve 16 bytes on stack that
 | 
| + * correspond to registers a0-a3.
 | 
| + *
 | 
| + * This code pushes all parameters from registers into the stack; thus, we keep
 | 
| + * all parameters on the stack as follows:
 | 
| + * top - arg0, arg1, arg2, arg3 .... argN
 | 
| + *
 | 
| + * On top of that we push the return address, so we will know where to return
 | 
| + * after the system call.
 | 
| + *
 | 
| + * After this code the stack layout must look like:
 | 
| + *
 | 
| + * sp+0: retaddr to user module
 | 
| + * sp+4: arg0 (system call argument)
 | 
| + * sp+8: arg1
 | 
| + * ..........
 | 
| + * sp+X: argN
 | 
| + *
 | 
| + * When service runtime serves a system call, it first creates a structure which
 | 
| + * utilizes these arguments. The structure is created by Decoder functions in
 | 
| + * nacl_syscall_handlers.c. (nacl_syscall_handlers.c is an automatically
 | 
| + * generated file and placed in
 | 
| + * scons-out//gen/native_client/src/trusted/service_runtime).
 | 
| + */
 | 
| +
 | 
| +  /* Place a0-a3 argument registers in the reserved 16-byte region in caller's
 | 
| +     stack frame (o32 ABI), and place return address on top of that. */
 | 
| +
 | 
| +  .cpload $t9
 | 
| +
 | 
| +  sw    $a3, 12($sp)
 | 
| +  sw    $a2,  8($sp)
 | 
| +  sw    $a1,  4($sp)
 | 
| +  sw    $a0,  0($sp)
 | 
| +  addiu $sp, $sp, -8
 | 
| +  sw    $ra,  4($sp)
 | 
| +  sw    $t5,  0($sp)
 | 
| +
 | 
| +  /* Load the __thread variable's offset into a3. */
 | 
| +  lui   $a3, %tprel_hi(gNaClThreadIdx)
 | 
| +  addiu $a3, $a3, %tprel_lo(gNaClThreadIdx)
 | 
| +
 | 
| +  /* Fetch the thread-local variable holding the thread index. */
 | 
| +  rdhwr $v1, $29
 | 
| +  addu  $a3, $v1, $a3
 | 
| +  lw    $a0, 0($a3)
 | 
| +
 | 
| +  /* Load the nacl_user entry of this thread.
 | 
| +   * a1 = nacl_user[a0*4] */
 | 
| +  lw    $a1,%got(nacl_user)($28)
 | 
| +  sll   $a0, $a0, 2
 | 
| +  addu  $a1, $a1, $a0
 | 
| +  lw    $a1, 0($a1)
 | 
| +
 | 
| +  sw $t6, NACL_THREAD_CONTEXT_OFFSET_T6($a1)
 | 
| +  sw $t7, NACL_THREAD_CONTEXT_OFFSET_T7($a1)
 | 
| +  sw $s0, NACL_THREAD_CONTEXT_OFFSET_S0($a1)
 | 
| +  sw $s1, NACL_THREAD_CONTEXT_OFFSET_S1($a1)
 | 
| +  sw $s2, NACL_THREAD_CONTEXT_OFFSET_S2($a1)
 | 
| +  sw $s3, NACL_THREAD_CONTEXT_OFFSET_S3($a1)
 | 
| +  sw $s4, NACL_THREAD_CONTEXT_OFFSET_S4($a1)
 | 
| +  sw $s5, NACL_THREAD_CONTEXT_OFFSET_S5($a1)
 | 
| +  sw $s6, NACL_THREAD_CONTEXT_OFFSET_S6($a1)
 | 
| +  sw $s7, NACL_THREAD_CONTEXT_OFFSET_S7($a1)
 | 
| +  sw $t8, NACL_THREAD_CONTEXT_OFFSET_T8($a1)
 | 
| +  sw $gp, NACL_THREAD_CONTEXT_OFFSET_GP($a1)
 | 
| +  sw $sp, NACL_THREAD_CONTEXT_OFFSET_SP($a1)
 | 
| +  sw $fp, NACL_THREAD_CONTEXT_OFFSET_FP($a1)
 | 
| +
 | 
| +  /* Restore the thread index. */
 | 
| +  srl   $a0, $a0, 2
 | 
| +
 | 
| +  /* Reserve 16-byte for arguments (o32 ABI) */
 | 
| +  addiu $sp, $sp, -16
 | 
| +  lw    $t9,%call16(NaClSyscallCSegHook)($gp)
 | 
| +  jr    $t9
 | 
| +  nop
 | 
| +
 | 
| +  /* NOTREACHED */
 | 
| +
 | 
| +  /*
 | 
| +   * If the thread returns, which must not happen, it will be halted
 | 
| +   * by the following instruction
 | 
| +   */
 | 
| +
 | 
| +  jr $0 /*NACL_HALT*/
 | 
| +
 | 
| 
 |