示例#1
0
文件: tramp.c 项目: Alkarex/mono
/*			     void *this_obj, stackval *arguments);  */
static inline unsigned int *
emit_prolog (unsigned int *pi, const gint SIZE, int hasthis )
{
	unsigned int *p = (unsigned int *)pi;
	// 9 instructions.
	alpha_ldah( p, alpha_gp, alpha_pv, 0 );  
	alpha_lda( p, alpha_gp, alpha_gp, 0 );     // ldgp gp, 0(pv)
	alpha_lda( p, alpha_sp, alpha_sp, -((SIZE & 8) ? (SIZE+8) : SIZE) ); // grow stack down SIZE (align to 16 bytes like gcc does)
	
	/* TODO: we really don't need to store everything.
	   alpha_a1: We have to store this in order to return the retval.
	   
	   alpha_a0: func pointer can be moved directly to alpha_pv
	   alpha_a3: don't need args after we are finished.
	   alpha_a2: will be moved into alpha_a0... if hasthis is true.
	*/
	/* store parameters on stack.*/
	alpha_stq( p, alpha_ra, alpha_sp, (SIZE-24) ); // ra
	alpha_stq( p, alpha_fp, alpha_sp, (SIZE-16) ); // fp
	alpha_stq( p, alpha_a1, alpha_sp, (SIZE-8) );  // retval
	
	/* set the frame pointer */
	alpha_mov1( p, alpha_sp, alpha_fp );
       
	/* move the args into t0, pv */
	alpha_mov1( p, alpha_a0, alpha_pv );
	alpha_mov1( p, alpha_a3, alpha_t0 );

	// Move the this pointer into a0.	
	if( hasthis )
	    alpha_mov1( p, alpha_a2, alpha_a0 );
	return p;
}
示例#2
0
文件: jit-apply-alpha.c 项目: 8l/lllm
void _jit_create_closure(unsigned char *buf, void *func, void *closure, void *_type) {
	alpha_inst inst = (alpha_inst) buf;

	/* Compute and load the global pointer (2 instructions) */
	alpha_ldah(inst,ALPHA_GP,ALPHA_PV,0);
	alpha_lda( inst,ALPHA_GP,ALPHA_GP,0);

	/* Allocate space for a new stack frame. (1 instruction) */
	alpha_lda(inst,ALPHA_SP,ALPHA_SP,-(13*8));

	/* Save the return address. (1 instruction) */
	alpha_stq(inst,ALPHA_RA,ALPHA_SP,0*8);

	/* Save integer register arguments as local variables (6 instructions) */
	alpha_stq(inst,ALPHA_A0,ALPHA_SP,1*8);
	alpha_stq(inst,ALPHA_A1,ALPHA_SP,2*8);
	alpha_stq(inst,ALPHA_A2,ALPHA_SP,3*8);
	alpha_stq(inst,ALPHA_A3,ALPHA_SP,4*8);
	alpha_stq(inst,ALPHA_A4,ALPHA_SP,5*8);
	alpha_stq(inst,ALPHA_A5,ALPHA_SP,6*8);

	/* Save floating-point register arguments as local variables (8 instructions) */
	alpha_stt(inst,ALPHA_FA0,ALPHA_SP, 7*8);
	alpha_stt(inst,ALPHA_FA1,ALPHA_SP, 8*8);
	alpha_stt(inst,ALPHA_FA2,ALPHA_SP, 9*8);
	alpha_stt(inst,ALPHA_FA3,ALPHA_SP,10*8);
	alpha_stt(inst,ALPHA_FA4,ALPHA_SP,11*8);
	alpha_stt(inst,ALPHA_FA5,ALPHA_SP,12*8);

	/* Call the closure handling function (1 instruction) */
	alpha_call(inst,func);

	/* Restore the return address (1 instruction) */
	alpha_ldq(inst,ALPHA_RA,ALPHA_SP,0*8);

	/* Restore integer register arguments (6 instructions) */
	alpha_ldq(inst,ALPHA_A0,ALPHA_SP,1*8);
	alpha_ldq(inst,ALPHA_A1,ALPHA_SP,2*8);
	alpha_ldq(inst,ALPHA_A2,ALPHA_SP,3*8);
	alpha_ldq(inst,ALPHA_A3,ALPHA_SP,4*8);
	alpha_ldq(inst,ALPHA_A4,ALPHA_SP,5*8);
	alpha_ldq(inst,ALPHA_A5,ALPHA_SP,6*8);

	/* Restore floating-point register arguments (8 instructions) */
	alpha_ldt(inst,ALPHA_FA0,ALPHA_SP, 7*8);
	alpha_ldt(inst,ALPHA_FA1,ALPHA_SP, 8*8);
	alpha_ldt(inst,ALPHA_FA2,ALPHA_SP, 9*8);
	alpha_ldt(inst,ALPHA_FA3,ALPHA_SP,10*8);
	alpha_ldt(inst,ALPHA_FA4,ALPHA_SP,11*8);
	alpha_ldt(inst,ALPHA_FA5,ALPHA_SP,12*8);

	/* restore the stack pointer (1 instruction) */
	alpha_lda(inst,ALPHA_SP,ALPHA_SP,(13*8));
}
示例#3
0
文件: tramp.c 项目: Alkarex/mono
static inline unsigned int *
emit_store_return_default(unsigned int *pi, const gint SIZE )
{
	// 2 instructions.
        unsigned int *p = (unsigned int *)pi;
	
	/* TODO: This probably do different stuff based on the value.  
	   you know, like stq/l/w. and s/f.
	*/
	alpha_ldq( p, alpha_t0, alpha_fp, (SIZE-8) );  // load void * retval
	alpha_stq( p, alpha_v0, alpha_t0, 0 );       // store the result to *retval.
	return p;
}
示例#4
0
文件: jit-apply-alpha.c 项目: 8l/lllm
void *_jit_create_redirector(unsigned char *buf, void *func, void *user_data, int abi) {
	alpha_inst inst = (alpha_inst) buf;

	/* Allocate space for a new stack frame. (1 instruction) */
	alpha_lda(inst,ALPHA_SP,ALPHA_SP,-(16*8));

	/* Save the return address. (1 instruction) */
	alpha_stq(inst,ALPHA_RA,ALPHA_SP,0*8);

	/* Save the frame pointer. (1 instruction) */
	alpha_stq(inst,ALPHA_FP,ALPHA_SP,1*8);

	/* Save the integer save registers (6 instructions) */
	alpha_stq(inst,ALPHA_S0,ALPHA_SP,2*8);
	alpha_stq(inst,ALPHA_S1,ALPHA_SP,3*8);
	alpha_stq(inst,ALPHA_S2,ALPHA_SP,4*8);
	alpha_stq(inst,ALPHA_S3,ALPHA_SP,5*8);
	alpha_stq(inst,ALPHA_S4,ALPHA_SP,6*8);
	alpha_stq(inst,ALPHA_S5,ALPHA_SP,7*8);

	/* Save the floating point save registers (8 instructions) */
	alpha_stt(inst,ALPHA_FS0,ALPHA_SP, 8*8);
	alpha_stt(inst,ALPHA_FS1,ALPHA_SP, 9*8);
	alpha_stt(inst,ALPHA_FS2,ALPHA_SP,10*8);
	alpha_stt(inst,ALPHA_FS3,ALPHA_SP,11*8);
	alpha_stt(inst,ALPHA_FS4,ALPHA_SP,12*8);
	alpha_stt(inst,ALPHA_FS5,ALPHA_SP,13*8);
	alpha_stt(inst,ALPHA_FS6,ALPHA_SP,14*8);
	alpha_stt(inst,ALPHA_FS7,ALPHA_SP,15*8);

	/* Set the frame pointer (1 instruction) */
	alpha_mov(inst,ALPHA_SP,ALPHA_FP);

	/* Compute and load the global pointer (2 instructions) */
	alpha_ldah(inst,ALPHA_GP,ALPHA_PV,0);
	alpha_lda( inst,ALPHA_GP,ALPHA_GP,0);

	/* Force any pending hardware exceptions to be raised. (1 instruction) */
	alpha_trapb(inst);

	/* Call the redirector handling function (6 instruction) */
	alpha_call(inst, func);

	/* Restore the return address. (1 instruction) */
	alpha_ldq(inst,ALPHA_RA,ALPHA_SP,0*8);

	/* Restore the frame pointer. (1 instruction) */
	alpha_ldq(inst,ALPHA_FP,ALPHA_SP,1*8);

	/* Restore the integer save registers (6 instructions) */
	alpha_ldq(inst,ALPHA_S0,ALPHA_SP,2*8);
	alpha_ldq(inst,ALPHA_S1,ALPHA_SP,3*8);
	alpha_ldq(inst,ALPHA_S2,ALPHA_SP,4*8);
	alpha_ldq(inst,ALPHA_S3,ALPHA_SP,5*8);
	alpha_ldq(inst,ALPHA_S4,ALPHA_SP,6*8);
	alpha_ldq(inst,ALPHA_S5,ALPHA_SP,7*8);

	/* Restore the floating point save registers (8 instructions) */
	alpha_ldt(inst,ALPHA_FS0,ALPHA_SP, 8*8);
	alpha_ldt(inst,ALPHA_FS1,ALPHA_SP, 9*8);
	alpha_ldt(inst,ALPHA_FS2,ALPHA_SP,10*8);
	alpha_ldt(inst,ALPHA_FS3,ALPHA_SP,11*8);
	alpha_ldt(inst,ALPHA_FS4,ALPHA_SP,12*8);
	alpha_ldt(inst,ALPHA_FS5,ALPHA_SP,13*8);
	alpha_ldt(inst,ALPHA_FS6,ALPHA_SP,14*8);
	alpha_ldt(inst,ALPHA_FS7,ALPHA_SP,15*8);

	/* Restore the stack pointer (1 instruction) */
	alpha_lda(inst,ALPHA_SP,ALPHA_SP,16*8);

	/* Force any pending hardware exceptions to be raised. (1 instruction) */
	alpha_trapb(inst);

	/* Jump to the function that the redirector indicated (1 instruction) */
	alpha_jsr(inst,ALPHA_RA,ALPHA_V0,1);

	/* Return the start of the buffer as the redirector entry point */
	return (void *)buf;
}
示例#5
0
文件: tramp.c 项目: Alkarex/mono
MonoPIFunc
mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor)
{
	unsigned int *p;
	unsigned int *buffer;
	MonoType* param;

	int i, pos;
	int alpharegs;
	int hasthis;
	int STACK_SIZE;
	int BUFFER_SIZE;
	int simple_type;
	int regbase;
	
	// Set up basic stuff.  like has this.	
	hasthis = !!sig->hasthis;
	alpharegs = AXP_GENERAL_REGS - hasthis;
	regbase  = hasthis?alpha_a1:alpha_a0 ;
	
	// Make a ballpark estimate for now.
	calculate_size( sig, &BUFFER_SIZE, &STACK_SIZE );
	
	// convert to the correct number of bytes.
	BUFFER_SIZE = BUFFER_SIZE * 4;

	
	// allocate.	
	buffer = p = (unsigned int *)malloc(BUFFER_SIZE);
	memset( buffer, 0, BUFFER_SIZE );
	pos = 8 * (sig->param_count - alpharegs - 1);
	
	// Ok, start creating this thing.
	p = emit_prolog( p, STACK_SIZE, hasthis );

	// copy everything into the correct register/stack space
	for (i = sig->param_count; --i >= 0; ) 
	{
		param = sig->params [i];
		
		if( param->byref )
		{
			if( i >= alpharegs )
			{
				// load into temp register, then store on the stack 
				alpha_ldq( p, alpha_t1, alpha_t0, ARG_LOC( i ));
				alpha_stq( p, alpha_t1, alpha_sp, pos );
				pos -= 8;
			}
			else
			{
				// load into register
				alpha_ldq( p, (regbase + i), alpha_t0, ARG_LOC( i ) );
			}
		}
		else
		{
			simple_type = param->type;
			if( simple_type == MONO_TYPE_VALUETYPE )
			{
                        	if (param->data.klass->enumtype)
                                	simple_type = param->data.klass->enum_basetype->type;
                        }
			
			switch (simple_type) 
			{
			case MONO_TYPE_VOID:
				break;
			case MONO_TYPE_BOOLEAN:
			case MONO_TYPE_CHAR:
			case MONO_TYPE_I1:
			case MONO_TYPE_U1:
			case MONO_TYPE_I2:
			case MONO_TYPE_U2:
			case MONO_TYPE_I4:
			case MONO_TYPE_U4:
				// 4 bytes - need to sign-extend (stackvals are not extended)
				if( i >= alpharegs )
				{
					// load into temp register, then store on the stack
					alpha_ldl( p, alpha_t1, alpha_t0, ARG_LOC( i ) );
					alpha_stq( p, alpha_t1, alpha_sp, pos );
					pos -= 8;
				}
				else
				{
					// load into register
					alpha_ldl( p, (regbase + i), alpha_t0, (ARG_LOC(i)) );
				}
				break;
			case MONO_TYPE_I:
			case MONO_TYPE_U:
			case MONO_TYPE_PTR:
			case MONO_TYPE_CLASS:
			case MONO_TYPE_OBJECT:
			case MONO_TYPE_SZARRAY:
			case MONO_TYPE_STRING:
			case MONO_TYPE_I8:
				// 8 bytes
				if( i >= alpharegs )
				{
					// load into temp register, then store on the stack
					alpha_ldq( p, alpha_t1, alpha_t0, ARG_LOC( i ) );
					alpha_stq( p, alpha_t1, alpha_sp, pos );
					pos -= 8;
				}
				else
				{
					// load into register
					alpha_ldq( p, (regbase + i), alpha_t0, ARG_LOC(i) );
				}
				break;
			case MONO_TYPE_R4:
			case MONO_TYPE_R8:
				/*
				// floating point... Maybe this does the correct thing.
				if( i > alpharegs )
				{
					alpha_ldq( p, alpha_t1, alpha_t0, ARG_LOC( i ) );
					alpha_cpys( p, alpha_ft1, alpha_ft1, alpha_ft2 );
					alpha_stt( p, alpha_ft2, alpha_sp, pos );
					pos -= 8;
				}
				else
				{
					alpha_ldq( p, alpha_t1, alpha_t0, ARG_LOC(i) );
					alpha_cpys( p, alpha_ft1, alpha_ft1, alpha_fa0 + i + hasthis );
				}
				break;
				*/
			case MONO_TYPE_VALUETYPE:
				g_error ("Not implemented: ValueType as parameter to delegate." );
				break;
			default:
				g_error( "Not implemented: 0x%x.", simple_type );
				break;	
			}
		}
	}
	
	// Now call the function and store the return parameter.
	p = emit_call( p, STACK_SIZE );
	p = emit_store_return_default( p, STACK_SIZE );
	p = emit_epilog( p, STACK_SIZE );

	if( p > buffer + BUFFER_SIZE )
		g_error( "Buffer overflow: got 0x%lx, expected <=0x%x.", (long)(p-buffer), BUFFER_SIZE );

	/* flush instruction cache to see trampoline code */
	asm volatile("imb":::"memory");
	
	return (MonoPIFunc)buffer;
}