⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fudge.c.3b

📁 cfront是最开始c++语言到C语言的转换工具
💻 3B
字号:
/*ident	"@(#)cls4:lib/task/task/fudge.c.3b	1.1" *//******************************************************************************* C++ source for the C++ Language System, Release 3.0.  This productis a new release of the original cfront developed in the computerscience research center of AT&T Bell Laboratories.Copyright (c) 1991 AT&T and UNIX System Laboratories, Inc.Copyright (c) 1984, 1989, 1990 AT&T.  All Rights Reserved.THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of AT&T and UNIX SystemLaboratories, Inc.  The copyright notice above does not evidenceany actual or intended publication of such source code.*******************************************************************************/#include <task.h>#include <stdio.h>#include "hw_stack.h"// 3B frame fudger//Frames not self-describing!//STACK GROWS UP#ifdef u3b	/*	 * On the 3B20, the call instruction is call num,dst	 * where num is the number of arguments to the function	 * and dst is the address of the called function.	 * There are 4 possible opcodes for the call instruction:	 * 3 are optimizations possible when num can be represented in 4 bits	 * (the usual case), and further depend on the addressing mode used.	 * This code assumes that destination addresses will only be 	 * pc-relative, absolute, or absolute deferred.	 */const GEN_CALL		= 0x78;const OPT_GEN_CALL	= 0x79;const PC_REL_CALL	= 0x77;const IMM_CALL		= 0xB9;const ABSOLUTE_DESC	= 0x08;const PC_REL_DESC	= 0x06;const ABSOLUTE_DEF_DESC	= 0x09;#define IS_CALL_OPCODE(instr)						\	(((MACHINE_BYTE)(instr) == (MACHINE_BYTE)GEN_CALL)	||	\	 ((MACHINE_BYTE)(instr) == (MACHINE_BYTE)OPT_GEN_CALL)	||	\	 ((MACHINE_BYTE)(instr) == (MACHINE_BYTE)PC_REL_CALL)	||	\	 ((MACHINE_BYTE)(instr) == (MACHINE_BYTE)IMM_CALL))const N_CALL_INSTR_SIZES = 3;short call_size[N_CALL_INSTR_SIZES] = {4, 6, 7};#undef	SAVE_OPERAND	/* not needed for u3b *//* src op is not important in decoding the call instruction on u3b */#define	SRC_OP_DESC(instr)		/* not needed for u3b */#define	IS_LEGAL_SRC_OP()	1#undef	SRC_OP_SIZE	/* not needed for u3b */const	OPCODE_SIZE = 1;const	OPERAND1_SIZE = 1;#define	DST_OP_DESC(instr)	\	(((unsigned char *)(instr))[OPCODE_SIZE] & 0x0f)#define IS_LEGAL_DST_OP(desc)			\	(((desc) == ABSOLUTE_DESC)	||	\	 ((desc) == PC_REL_DESC)	||	\	 ((desc) == ABSOLUTE_DEF_DESC)		\	)#define	HAS_LEGAL_OPERANDS(call_instr)			\	(IS_LEGAL_DST_OP((DST_OP_DESC(poss_callp))) ||	\	 (call_instr[0] == PC_REL_CALL))/* Given a pointer to a call instruction, * yield a pointer to the called function */unsigned intcall_dst_ptr(unsigned char* callp){	int offset = 0;	// points past operand1 and/or descriptor to address or offset	unsigned char* dst_op_p = callp + OPCODE_SIZE + OPERAND1_SIZE;	switch(*callp)	{	case PC_REL_CALL:			// 16-bit pc-relative address		offset = dst_op_p[0] << 8 | dst_op_p[1];		if (callp[1] & 0x80)		// negative offset			offset = -(offset);		unsigned char* next_pc = callp + 4;	// relative to NEXT pc		return (unsigned int)((short*)next_pc + offset);	case GEN_CALL:	case OPT_GEN_CALL:		switch(DST_OP_DESC(callp))	{		case ABSOLUTE_DESC:	// 24-bit absolute address			return	(dst_op_p[0] << 20 |				 dst_op_p[1] << 12 |				 dst_op_p[2] <<  4 |				 dst_op_p[3] >>  4 ) & 0x00ffffff;		case ABSOLUTE_DEF_DESC:	// 24-bit absolute deferred address			int* addr_p =				(int*) ((dst_op_p[0] << 20 |					 dst_op_p[1] << 12 |					 dst_op_p[2] <<  4 |					 dst_op_p[3] >>  4 ) & 0x00ffffff);			return (unsigned int)(*addr_p);		case PC_REL_DESC:	// 24-bit pc-relative address			offset = (dst_op_p[0] << 20 |				  dst_op_p[1] << 12 |				  dst_op_p[2] <<  4 |				  dst_op_p[3] >>  4 );			if (dst_op_p[0] & 0x08)	// negative offset				offset |= 0xff000000;			else			// positive offset				offset &= 0x00ffffff;			return (unsigned int)(callp + offset);		default:			// illegal descriptor			object::task_error(E_FUNCS, (object*)0);		}	case IMM_CALL:				// 24-bit immediate address		return	(dst_op_p[0] << 20 |			 dst_op_p[1] << 12 |			 dst_op_p[2] <<  4 |			 dst_op_p[3] >>  4 ) & 0x00ffffff;	default:				// illegal call instruction		object::task_error(E_FUNCS, (object*)0);	}}	/* call_dst_ptr */#else	/* m32:  u3b2, u3b5, u3b15 *//* * On the 3B2, the call instruction is CALL src,dst * where src is the address of the new ap (where the args were * already pushed on the stack) and dst is the address of the * called function.  src and dst can be various lengths: * src will be a byte, halfword, or word displacement * and dst will be absolute, or be a byte, halfword, or word displacement. * Byte displacement = 2 bytes, halfword = 3, word = 5; * the opcode = 1 byte; absolute = 5 bytes--12 possible combinations * and 6 possible instr lengths. */#define IS_CALL_OPCODE(instr) ((MACHINE_BYTE)(instr) == (MACHINE_BYTE)0x2c)const BYTE_DISPL	= 0xC0;const HALFWORD_DISPL	= 0xA0;const WORD_DISPL	= 0x80;const ABSOLUTE		= 0x70;const REG_SP		= 0x0C;const REG_PC		= 0x0F;const N_CALL_INSTR_SIZES = 6;short call_size[N_CALL_INSTR_SIZES] = {5, 6, 7, 8, 9, 11};/* CALL's src operand descriptor needed to determine size of src operand */#define SRC_OP_DESC(instr)	(((unsigned char *)(instr))[1])#define SRC_OP_SIZE(desc) 				\	((MODE_FIELD(desc) == BYTE_DISPL)	? 2 :	\	 (MODE_FIELD(desc) == HALFWORD_DISPL)	? 3 :	\	 (MODE_FIELD(desc) == WORD_DISPL)	? 5 :	\	 ((object::task_error(E_FUNCS, (object*)0)))		\	)const	OPCODE_SIZE = 1;const	DESC_SIZE = 1;#define	DST_OP_DESC(instr)		\	(((unsigned char *)(instr))	\		[OPCODE_SIZE + SRC_OP_SIZE(SRC_OP_DESC(instr))])#define	MODE_FIELD(desc)	((desc) & 0xf0)#define	REG_FIELD(desc)		((desc) & 0x0f)#define IS_LEGAL_SRC_OP(desc)	/* assumes sp-relative displ */	\	(((MODE_FIELD(desc) == BYTE_DISPL)		||	\	  (MODE_FIELD(desc) == HALFWORD_DISPL)		||	\	  (MODE_FIELD(desc) == WORD_DISPL)			\	 ) && (REG_FIELD(desc) == REG_SP)			\	)/* destination displacement is probably pc-relative, but we don't * make that assumption.  It could be a call through a function pointer. */#define IS_LEGAL_DST_OP(desc)						\	((MODE_FIELD(desc) == BYTE_DISPL)		||		\	 (MODE_FIELD(desc) == HALFWORD_DISPL)		||		\	 (MODE_FIELD(desc) == WORD_DISPL)		||		\	 ((MODE_FIELD(desc) == ABSOLUTE) && (REG_FIELD(desc) == REG_PC))\	)#define	HAS_LEGAL_OPERANDS(call_instr)			\	(IS_LEGAL_SRC_OP((SRC_OP_DESC(call_instr)))	\	&& IS_LEGAL_DST_OP((DST_OP_DESC(call_instr))))/* Given a pointer to a call instruction, yield a pointer to * the called function */unsigned intcall_dst_ptr(unsigned char* callp){	int sop_size = SRC_OP_SIZE(SRC_OP_DESC(callp));	unsigned char* dst_op_p =		/* points past the dst desc, to addr or offset */		callp + OPCODE_SIZE + sop_size + DESC_SIZE;	int offset = 0;		// offset for displacement modes	switch(MODE_FIELD(DST_OP_DESC(callp))) {	case BYTE_DISPL:		offset = dst_op_p[0];		if(*dst_op_p & 0x80) {			/* negative--do sign extension for offset */			offset |= 0xffffff00;		}		return (unsigned int)(callp + offset);	case HALFWORD_DISPL:		// bytes are in reverse order, must flip positions		offset = dst_op_p[0] | dst_op_p[1] << 8;		if(dst_op_p[1] & 0x80) {			/* negative--do sign extension for offset */			offset |= 0xffff0000;		}		return (unsigned int)(callp + offset);	case WORD_DISPL:		// bytes are in reverse order, must flip positions		offset = dst_op_p[0]       |			 dst_op_p[1] <<  8 |			 dst_op_p[2] << 16 |			 dst_op_p[3] << 24;		/* don't need sign extension */		return (unsigned int)(callp + offset);	case ABSOLUTE:		return			dst_op_p[0]       |			dst_op_p[1] <<  8 |			dst_op_p[2] << 16 |			dst_op_p[3] << 24;	default:		object::task_error(E_FUNCS, (object*)0);	}}	/* call_dst_ptr */#endif	/* m32:  u3b2, u3b5, u3b15 */FrameLayout::FrameLayout(int* fp){	/*	 * Given a frame pointer, find the number of regs saved in the frame.	 * The idea is that the instruction immediately before the return pc	 * is the function call, and contains a pointer to the first	 * instruction in the function denoted by the fp, which will be a save	 * instruction. We can decode the save instruction to find how many	 * registers were saved.	 */	int*   return_pc = (int*)OLD_PC(fp);	unsigned char* callp = NULL;	/* Because this method is nondeterministic, try all combinations	   instead of stopping when one fits */	for(int i = 0; i < N_CALL_INSTR_SIZES; i++) {		unsigned char* poss_callp =			(unsigned char *)return_pc - call_size[i];		if ((IS_CALL_OPCODE(*poss_callp))		     && HAS_LEGAL_OPERANDS(poss_callp)) {	    		if(!callp) callp = poss_callp;	    		else {	// try some heuristics to disambiguate				// (Don't try to dereference dst ptr				// until sure, or necessary to disambiguate,				// to avoid unnecessary core dumps.)				// If first callp dst points to a save,				// assume that is the instruction we want.				if (!IS_SAVE_OPCODE(				     *(unsigned char *)(call_dst_ptr(callp))) ) {					if (IS_SAVE_OPCODE(					    *(unsigned char *)(call_dst_ptr(poss_callp))) ) {						callp = poss_callp;					} else {						// neither is right, go on						callp = 0;					}									}			}		}	}	if (callp == NULL) object::task_error(E_FUNCS, (object*)0);	//No match!	unsigned int func_addr = call_dst_ptr(callp);	if (!(IS_SAVE_OPCODE( *(unsigned char *)func_addr) ))		object::task_error(E_FUNCS, (object*)0);	n_saved = N_SAVED_REGS(func_addr);}/* * Fudge frame of function-defined-by-f_fp (called "f" below) * so that that function returns to its grandparent, * in particular, so a parent task returns to the function that * called the derived constructor (de_ctor), skipping de_ctor; * the child will return to the derived constructor, which is its "main." * To do this we will overwrite the old fp, ap, and pc (those saved by * f) with the old-old ones (those saved by f's caller), * and we will overwrite the register save area with registers saved by  * f's caller (referred to as "skip" below). * * There are 2 register-save cases to deal with: *     1. skip_n_saved <= f_n_saved *     2. skip_n_saved >  f_n_saved * * These are handled as follows: *     1. copy the saved skip_regs over the corresponding f_regs, *        leaving any additional saved f_regs intact. *        f's restore instruction will be correct. *     2. f's restore instruction will restore too few regs, must take special *	  care to see that the extras are restored properly. *	  -Copy saved skip_regs over any corresponding f_regs, *	  -If fudge_return saved more regs than f did, then *	   copy saved extra saved skip_regs over any corresponding fudge_regs, *	  -If more extra skip_regs (not saved by either f or fudge_return, *	   and therefore not used by either) remain, restore them explicitly. *	   They will not be disturbed by the return from fudge_return or f, */voidtask::fudge_return(int* f_fp){	register int*	fp = f_fp;		// fp of frame-to-be-fudged	FrameLayout	lo(fp);			// frame to be fudged	register int*	skip_fp = (int*)OLD_FP(fp); // fp for f's caller (skip)	FrameLayout	skip_lo(skip_fp);	// frame for skip	OLD_PC(fp) = OLD_PC(skip_fp);	OLD_AP(fp) = OLD_AP(skip_fp);	OLD_FP(fp) = OLD_FP(skip_fp);	// finally copy saved regs	register int* from = LAST_SAVED_REG_P(skip_fp, skip_lo.n_saved);	register int* to   = LAST_SAVED_REG_P(fp, lo.n_saved);	register int i;	if(lo.n_saved >= skip_lo.n_saved) {		// copy the saved skip regs over the corresponding f regs,		// leaving any additional saved f regs intact.		for(i = skip_lo.n_saved; i > 0; i--) {			*to-- = *from--;		}	} else  {	// lo.n_saved < skip_lo.n_saved--take care!		// copy the saved skip regs over any corresponding		// f regs.		for(i = lo.n_saved; i > 0; i--) {			*to-- = *from--;		}		int extra = skip_lo.n_saved - lo.n_saved;		// If fudge_return saved more regs than f, extra skip_regs		// should be copied over any corresponding fudge_return regs.		int*	fr_fp = FP();		// fp for fudge_return		FrameLayout	fr_lo(fr_fp);	// frame for fudge_return		if (fr_lo.n_saved >= lo.n_saved) {			to = LAST_SAVED_REG_P(fr_fp, fr_lo.n_saved) - lo.n_saved;			int n;			int d = fr_lo.n_saved - lo.n_saved;			if (d >= extra)	{	// room for all extra skip_regs				n = extra;			} else {				n = d;			}			for(i = n; i > 0; i--) {				*to-- = *from--;				extra--;			}		}		if (extra) { // Remaining skip regs must be explicitly restored.			int r = skip_lo.n_saved - extra + 1;			for (i = extra; i > 0; i--) {				switch (r++) {				case 6:					set_r3(from);					from--;					break;				case 5:					set_r4(from);					from--;					break;				case 4:					set_r5(from);					from--;					break;				case 3:					set_r6(from);					from--;					break;				case 2:					set_r7(from);					from--;					break;				case 1:					set_r8(from);					from--;					break;				}			}		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -