solo_asms.s 5.22 KB
/*
 * Copyright (C) 1996-1998 by the Board of Trustees
 *    of Leland Stanford Junior University.
 * 
 * This file is part of the SimOS distribution. 
 * See LICENSE file for terms of the license. 
 *
 */

/*****************************************************************
 * solo_asms.s
 *
 * Assembly routines needed by solo MIPSY. Solo mipsy currently works
 * by linking directly into an application. This only works in
 * uniprocessor mode right now.
 *****************************************************************/

#include <asm.h>
#include <regdef.h>
#include <sys.s>
#include "mips_arch.h"

/*
 * StartApp(int argc, char *argv[], int environLen, char *environ[], 
 *          void *newStackPtr)
 * Setup the stack as if the kernel does during an exec and then
 * jump to the entry point.
 */

LEAF(SetupStack)
        /* 
         * t4 will hold the simulated stack pointer
         */
	lw	t4,16(sp)

       	/*
	 * Compute the size of the stack as 
	 *   ((argc + numEnv)*4 + 64) & ~7;
	 */
	addu	t0,a0,a2
	mul	t0,t0,4
	addu	t0,t0,64
	and	t0,t0,-8
	subu  	t4,t4,t0

	/*
	 * 
	 * Build the stack as 
	 *
	 *  environ Array
	 *  argv    Array
	 *  argc
 	 */
	sw	a0,0(t4)

	addu	t2,t4,4

	/*
	 * Copy argv including null pointer.
	 */
	
1:
	lw	t1,0(a1)
	sw	t1,0(t2)
	addu	a1,a1,4
	addu	t2,t2,4
	bne	t1,0, 1b

	/*
	 * Copy environ include null pointer.
	 */

2:
	lw	t1,0(a3)
	sw	t1,0(t2)
	addu	a3,a3,4
	addu	t2,t2,4
	bne	t1,0, 2b
        .set    noreorder
        addi    v0, t4, 0
        nop
        j       ra
        .set    noreorder

        END(StartApp)

	

#ifdef NOTDEF
        /* Not using this anymore */        
                
/*****************************************************************
 * SoloMipsyEnter
 *
 * Store needed registers into the simulator's structure.
 * Set the stack pointer with room for the simulator's stack.
 * Jump into the simulation with the return address being the first
 *	instruction to start simulating. 
 *
 * a0 - Pointer to mipsy's register file
 * a1 - Function to jump to when the regs are saved
 *****************************************************************/
	.text
	.align 4
	.extern holdSP 32

	.align 4
	.extern holdRA 32

	.align 4
	.extern holdGP 32

        .align 4
        .extern holdPE 32

LEAF(SoloMipsyEnter)
XLEAF(solomipsyenter_)

	/* Store the callers registers in Mipsy's register 
   		     file (loaded into a0) */

	la	a0, PE
	sw	s0, REG_S0*4(a0)
	sw	s1, REG_S1*4(a0)
	sw	s2, REG_S2*4(a0)
	sw	s3, REG_S3*4(a0)
	sw	s4, REG_S4*4(a0)
	sw	s5, REG_S5*4(a0)
	sw	s6, REG_S6*4(a0)
	sw	s7, REG_S7*4(a0)
	sw	ra, REG_RA*4(a0) 

	sw	gp, REG_GP*4(a0)
	sw	sp, REG_SP*4(a0)   /* Simulated stack */ 
	sw	s8, REG_FP*4(a0)   /* Another name for fp */
	
        s.d     $f0, REG_FPR_0(a0)
        s.d     $f2, REG_FPR_2(a0)
        s.d     $f4, REG_FPR_4(a0)
        s.d     $f6, REG_FPR_6(a0)
        s.d     $f8, REG_FPR_8(a0)
        s.d     $f10, REG_FPR_10(a0)
        s.d     $f12, REG_FPR_12(a0)
        s.d     $f14, REG_FPR_14(a0)
        s.d     $f16, REG_FPR_16(a0)
        s.d     $f18, REG_FPR_18(a0)

	lw	sp, mipsyStackTop 
	lui	s0, 0xffff
	ori	s0, s0, 0xfff8
	and	sp, s0, sp

	la	a0, PE

	
	/* Original ra - the instruction after the MipsyStart() */
	lw	ra, REG_RA*4(a0)

	/* Set the pc to return to the caller */
	la 	t0, StartSimLabel
	sw	t0, REG_PC*4(a0)
	addi	t0, 4
	sw	t0, REG_NPC*4(a0)

	/* Now call the simulator - a0 still has the registers */
	.set noreorder
	la	a1, SoloRun
	la 	t9, SoloRun
	nop
	jal	a1
	nop
	.set reorder
	
END(SoloMipsyEnter)

StartSimLabel:
	.set noreorder
	nop
	j	ra
	nop
	.set reorder



#endif /* NOT DEF */
        
/*****************************************************************
 * MipsyHandleSyscall
 *
 *****************************************************************/

/* Until I figure out exactly which registers are needed, I'll save */
/* every register */ 

LEAF(MipsyHandleSyscall)
	sw	sp, holdSP
	sw	ra, holdRA
        sw      a0, holdPE
        sw	gp, holdGP
 
	move 	t0, a0

	lw 	v1, REG_V1*4(t0)
	lw 	v0, REG_V0*4(t0)

	lw	a0, REG_A0*4(t0)
	lw	a1, REG_A1*4(t0)
	lw	a2, REG_A2*4(t0)
	lw	a3, REG_A3*4(t0)

	lw	gp, REG_GP*4(t0)
	lw 	sp, REG_SP*4(t0) 

	/* Test if this was an exit call */
	li	t1, 1001
	beq	t1, v0, ExitLabel

        .set noreorder
        lw      v0, REG_V0*4(t0)
	syscall
	.set reorder
        
	lw	t0, holdPE

	sw 	v0, REG_V0*4(t0)
	sw 	v1, REG_V1*4(t0)

	sw	a0, REG_A0*4(t0)
	sw	a1, REG_A1*4(t0)
	sw	a2, REG_A2*4(t0)
	sw	a3, REG_A3*4(t0)
	
	sw	sp, REG_SP*4(t0) 

	lw      gp, holdGP        
	lw	sp, holdSP
	lw	ra, holdRA
	j	ra

ExitLabel:
	jal	SoloExit
                
       	.set noreorder
        nop

       	lw 	sp, holdSP
	lw 	ra, holdRA
	nop
	j 	ra
	.set reorder
END(MipsyHandleSyscall)


/* Optimization for the page hash function. Everything is currently hardcoded
   so be careful. The input is a unsigned long long in registers a0 and a1, and
   the output is an unsigned in register v0. This is big endian, so a0 holds the
   high order bits of the address. This routine is written for a page size of 
   4k (shift right 12 bits) and a hash mapping that takes the low order 13 bits 
   (8192 buckets). */
LEAF(mapping_hash)
        srl     a1, a1, 12
        sll     a0, a0, 20
        or      v0, a0, a1
        andi    v0, v0, 0x00001fff
        j       ra
END(mapping_hash)