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

📄 aoperand.c

📁 早期freebsd实现
💻 C
字号:
/*- * Copyright (c) 1986 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Computer Consoles Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)Aoperand.c	7.1 (Berkeley) 12/6/90 */#include	"align.h"#define	illegal(x) ((look_at->add_modes & x)==0)#define	legal(x) !illegal(x)struct oprnd *operand(infop, number)register process_info *infop;int	number;/* *	Enter with pc pointing to an operand descriptor *	in the 'text'. Decode the addressing mode, get *	the effective address and some data from there. *	Leave pc on the next oerand specifier or opcode. *	Returns a pointer to a 'decoded operand' structure, *	actually one of the 4 pre-allocated . * *	This routine should be called in such a sequence *	that pc will not have to be backed up to get some *	operand. For example, operand(0) and then operand(1) *	and then operand(2) is OK. Even operand(0), operand(1), *	operand(1) is OK. The rule is that operand(N) should not *	be called before operand(N-1) was. *	 ***********************************************************/{	register struct oprnd *next;	register struct operand_des *look_at;	register int header,reg_num,shift_count, displ;	register int keep_last;	next = &decoded[number]; 	if (number <= last_operand) return(next);	if (number == last_operand+1) last_operand = number;	else	{		printf ("Wrong sequence of OPERAND calls (alignment code)\n");		return (&decoded[number]);	};	look_at  = &Table[opCODE].operand[number];	next->data2 = 0;		/* Prepare for quad fetch */	next->length = look_at->length;	if (look_at->add_modes == Brd)	{ 		next->mode = Add;		switch(look_at->length)		{ 		case 1: 			displ = get_byte(infop, pc);			pc++; 			break; 		case 2: 			displ = get_word(infop, pc); 			pc +=2; 			break;		default: 			printf ("Wrong branch displacement(alignment code)\n");		}; 		next->address = pc+displ; 		return(next); 	};		/* Not branch displacement, real operand */	header = get_byte(infop, pc) & 0xff; 	pc++; 	reg_num = header & 0xf;	switch (header >> 4 & 0xf) { 	case 0: 			/* Short literals */	case 1: 	case 2: 	case 3:		if (illegal(Lit)) exception(infop, ILL_ADDRMOD);		next->mode = Imm; 		next->data = header; 		break;	case 4: 			/* Indexed register */		if (illegal(Add) || reg_num==PCOUNTER || reg_num==SPOINTER)			exception (infop, ILL_ADDRMOD);		keep_last = last_operand;		last_operand = number - 1; /* To get real results */		next = operand(infop, number);   /* Get base address (recursive) */		last_operand = keep_last;		if		    (! (next->mode & Indx)) exception (infop, ILL_ADDRMOD);		switch (look_at->length)		{ 		case 1: 			shift_count = 0; 			break; 		case 2: 			shift_count = 1; 			break;		case 4: 			shift_count = 2; 			break; 		case 8: 			shift_count = 3; 			break;		default: 			printf("Wrong data length in table(alignment code)\n");		}; 		next->address += (Register(infop,reg_num) << shift_count);		next->mode |= (look_at->add_modes & M); /* Set R/W bits */		trytoread (infop,next,number);		break;	case 5: 			/* Direct register */		if (illegal (Dir) || reg_num==PCOUNTER ||		    reg_num==SPOINTER && legal(R)) exception (infop, ILL_ADDRMOD);		next->mode = Dir; 		next->data = Register(infop,reg_num); 		next->mode |= (look_at->add_modes & M); /* Set R/W bits */		next->reg_number = reg_num; 		if (look_at->length == 8)		{			if (reg_num >= SPOINTER-1 || (reg_num & 1)==1 ) 				exception (infop, ILL_ADDRMOD);			else next->data2 = Register(infop,reg_num+1);		};		break;	case 6: 			/* Indirect register */		if (illegal(Add) || reg_num==PCOUNTER )			exception (infop, ILL_ADDRMOD); 		next->mode = Add; 		next->mode |= (look_at->add_modes & M); /* Set R/W bits */		if (reg_num != SPOINTER) next->mode |= Indx;  /* (sp) not indexable*/		next->reg_number = reg_num;		next->address = Register(infop,reg_num);		trytoread (infop,next,number);		break;	case 7: 			/* Autodecrement SP */		if (illegal(Add) || reg_num!=SPOINTER || look_at->length != 4 ||		    legal(R)) exception (infop, ILL_ADDRMOD);		next->mode = SPmode;  	/* Implies Add */		next->mode |= W; 	/* Set R/W bits */		next->reg_number = SPOINTER; 		next->length = 4;	/* Regardless of big table */		sp -= 4;		next->address = sp; 		break;	case 8: 			/* Immediate or (sp)+ */		switch (reg_num) { 		case 8: 		/* Immediate byte */			if (illegal(Imm)) exception (infop, ILL_ADDRMOD);			next->mode = Imm; 			next->data = get_byte(infop, pc); 			pc++; 			break;		case 9: 		/* Immediate word */			if (illegal(Imm)) exception (infop, ILL_ADDRMOD);			next->mode = Imm; 			next->data = get_word(infop, pc); 			pc +=2; 			break;		case 0xf : 		/* Immediate longword */			if (illegal(Imm)) exception (infop, ILL_ADDRMOD);			next->mode = Imm; 			next->data = get_longword(infop, pc); 			pc +=4; 			break;		case 0xe: 		/* Autoincrement sp */			if (illegal(Add) || legal(W) ||				look_at->length != 4) exception (infop, ILL_ADDRMOD);			next->mode = SPmode;	/* Implies Add */			next->reg_number = SPOINTER;			next->address = sp; 		        next->data = get_longword(infop, sp);			next->length = 4;	/* Regardless of big table */			sp += 4; 			break;		default: 			exception (infop, ILL_ADDRMOD);		};		if (look_at -> length == 8)	/* Quadword fetch,not (sp)+ */		{			next->data2 = next->data;			if (next->data2 >= 0) next->data = 0;			else next->data = -1;		}		break;	case 9: 			/* Autoincrement deferred SP or PC */		if (reg_num !=PCOUNTER && reg_num !=SPOINTER )			exception (infop, ILL_ADDRMOD);		if (reg_num == PCOUNTER && illegal(Abs) ||		    reg_num == SPOINTER && illegal(Add))			exception (infop, ILL_ADDRMOD);		next->mode = Add | (look_at->add_modes & M) | Indx; 		next->address = get_longword (infop, (reg_num == PCOUNTER)?pc : sp ); 		Replace (infop,reg_num, Register(infop,reg_num)+4);		trytoread (infop,next,number);		break;	case 0xa:			/* Register or PC + byte displacement */		if (reg_num != PCOUNTER && illegal(Add) ||		    reg_num == PCOUNTER && illegal(Pcrel) ) exception (infop, ILL_ADDRMOD);		next->mode = Add | (look_at->add_modes & M); 		if (reg_num != SPOINTER &&			look_at->add_modes != PR) next->mode |= Indx;		displ = get_byte(infop,pc); 		pc++;		next->address = Register(infop,reg_num)+displ;		trytoread (infop,next,number);		break;	case 0xb:			/* Same, indirect */ 		if (illegal(Add)) exception (infop, ILL_ADDRMOD);		next->mode = Add | (look_at->add_modes & M) | Indx; 		displ = get_byte(infop,pc); 		pc++;		next->address = get_longword(infop, Register(infop,reg_num)+displ);		trytoread (infop,next,number);		break;	case 0xc:			/* Register or PC + word displacement */		if (reg_num != PCOUNTER && illegal(Add) ||		    reg_num == PCOUNTER && illegal(Pcrel) ) exception (infop, ILL_ADDRMOD);		next->mode = Add | (look_at->add_modes & M); 		if (reg_num != SPOINTER &&			look_at->add_modes != PR) next->mode |= Indx;		displ = get_word(infop,pc); 		pc +=2;		next->address = Register(infop,reg_num)+displ;		trytoread (infop,next,number);		break;	case 0xd:			/* Same, indirect */ 		if (illegal(Add)) exception (infop, ILL_ADDRMOD);		next->mode =Add | (look_at->add_modes & M) | Indx ; 		displ = get_word(infop,pc); 		pc +=2;		next->address = get_longword (infop,Register(infop,reg_num)+displ);		trytoread (infop,next,number);		break;	case 0xe:		/* Register or PC + longword displacement */		if (reg_num != PCOUNTER && illegal(Add) ||		    reg_num == PCOUNTER && illegal(Pcrel) ) exception (infop, ILL_ADDRMOD);		next->mode = Add | (look_at->add_modes & M); 		if (reg_num != SPOINTER &&			look_at->add_modes != PR) next->mode |= Indx;		displ = get_longword(infop,pc); 		pc += 4;		next->address = Register(infop,reg_num)+displ;		trytoread (infop,next,number);		break;	case 0xf:			/* Same, indirect */ 		if (illegal(Add)) exception (infop, ILL_ADDRMOD);		next->mode = Add | (look_at->add_modes & M) | Indx; 		displ = get_longword(infop,pc); 		pc +=4;		next->address = get_longword(infop, Register(infop,reg_num)+displ);		trytoread (infop,next,number);	};	return(next);}trytoread (infop,pointer,number)process_info	*infop;struct oprnd	*pointer;int		number;/*/*	Receives the opcode operand number and a pointer/*	to the 'decoded' operand structure./*	If it's defined as readable data in the big table,/*	it returns the data, sign extended./*/**********************************************************/{	register struct operand_des *look_at;		look_at  = &Table[opCODE].operand[number];	if (legal(R))	switch (look_at->length)	{	case 1:		pointer->data = get_byte (infop,pointer->address);		break;	case 2:		pointer->data = get_word (infop,pointer->address);		break;	case 4: 		pointer->data = get_longword (infop,pointer->address);		break;	case 8: 		pointer->data = get_longword (infop,pointer->address);		pointer->data2 = get_longword (infop,pointer->address+4);		break;	default:		printf ("Wrong data length in table (alignment code)\n");	};}

⌨️ 快捷键说明

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