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

📄 m68k.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
			case '3':				tmpreg&=0xFF;			case '8':			case 'C':				install_operand(s[1],tmpreg);				break;			default:				as_fatal("Internal error:  Unknown mode #%c",s[1]);			}			break;		case '+':		case '-':		case 'A':			install_operand(s[1],opP->reg-ADDR);			break;		case 'B':			tmpreg=get_num(opP->con1,80);			switch(s[1]) {			case 'g':				if(opP->con1->e_siz) {	/* Deal with fixed size stuff by hand */					switch(opP->con1->e_siz) {					case 1:						add_fix('b',opP->con1,1);						break;					case 2:						add_fix('w',opP->con1,1);						addword(0);						break;					case 3:						add_fix('l',opP->con1,1);						addword(0);						addword(0);						break;					default:						as_fatal("Bad size for expression %d",opP->con1->e_siz);					}				} else if(subs(opP->con1)) {						/* We can't relax it */					the_ins.opcode[the_ins.numo-1]|=0xff;					add_fix('l',opP->con1,1);					addword(0);					addword(0);				} else if(adds(opP->con1)) {					if (flagseen['m'] && 					    (the_ins.opcode[0] >= 0x6200) &&					    (the_ins.opcode[0] <= 0x6f00)) {					  add_frag(adds(opP->con1),offs(opP->con1),TAB(BCC68000,SZ_UNDEF));					} else {						add_frag(adds(opP->con1),offs(opP->con1),TAB(BRANCH,SZ_UNDEF));					}				} else {					/* JF:  This is the WRONG thing to do					add_frag((symbolS *)0,offs(opP->con1),TAB(BRANCH,BYTE)); */					the_ins.opcode[the_ins.numo-1]|=0xff;					offs(opP->con1)+=4;					add_fix('l',opP->con1,1);					addword(0);					addword(0);				}				break;			case 'w':				if(isvar(opP->con1)) {				    /* check for DBcc instruction */					if ((the_ins.opcode[0] & 0xf0f8) ==0x50c8) {					    /* size varies if patch */					    /* needed for long form */						add_frag(adds(opP->con1),offs(opP->con1),TAB(DBCC,SZ_UNDEF));						break;					}						/* Don't ask! */					opP->con1->e_exp.X_add_number+=2;					add_fix('w',opP->con1,1);				}				addword(0);				break;			case 'c':				if(opP->con1->e_siz) {					switch(opP->con1->e_siz) {					case 2:						add_fix('w',opP->con1,1)						addword(0);						break;					case 3:						the_ins.opcode[the_ins.numo-1]|=0x40;						add_fix('l',opP->con1,1);						addword(0);						addword(0);						break;					default:						as_bad("Bad size for offset, must be word or long");						break;					}				} else if(subs(opP->con1)) {					add_fix('l',opP->con1,1);					add_frag((symbolS *)0,(long)0,TAB(FBRANCH,LONG));				} else if(adds(opP->con1)) {					add_frag(adds(opP->con1),offs(opP->con1),TAB(FBRANCH,SZ_UNDEF));				} else {					/* add_frag((symbolS *)0,offs(opP->con1),TAB(FBRANCH,SHORT)); */					the_ins.opcode[the_ins.numo-1]|=0x40;					add_fix('l',opP->con1,1);					addword(0);					addword(4);				}				break;			default:				as_fatal("Internal error:  operand type B%c unknown",s[1]);			}			break;		case 'C':		/* Ignore it */			break;		case 'd':		/* JF this is a kludge */			if(opP->mode==AOFF) {				install_operand('s',opP->reg-ADDR);			} else {				char *tmpP;				tmpP=opP->con1->e_end-2;				opP->con1->e_beg++;				opP->con1->e_end-=4;	/* point to the , */				baseo=m68k_reg_parse(&tmpP);				if(baseo<ADDR+0 || baseo>ADDR+7) {					as_bad("Unknown address reg, using A0");					baseo=0;				} else baseo-=ADDR;				install_operand('s',baseo);			}			tmpreg=get_num(opP->con1,80);			if(!issword(tmpreg)) {				as_warn("Expression out of range, using 0");				tmpreg=0;			}			addword(tmpreg);			break;		case 'D':			install_operand(s[1],opP->reg-DATA);			break;		case 'F':			install_operand(s[1],opP->reg-FPREG);			break;		case 'I':			tmpreg=1+opP->reg-COPNUM;			if(tmpreg==8)				tmpreg=0;			install_operand(s[1],tmpreg);			break;		case 'J':		/* JF foo */			switch(opP->reg) {			case SFC:				tmpreg=0;				break;			case DFC:				tmpreg=0x001;				break;			case CACR:				tmpreg=0x002;				break;			case USP:				tmpreg=0x800;				break;			case VBR:				tmpreg=0x801;				break;			case CAAR:				tmpreg=0x802;				break;			case MSP:				tmpreg=0x803;				break;			case ISP:				tmpreg=0x804;				break;			default:				abort();			}			install_operand(s[1],tmpreg);			break;		case 'k':			tmpreg=get_num(opP->con1,55);			install_operand(s[1],tmpreg&0x7f);			break;		case 'l':			tmpreg=opP->reg;			if(s[1]=='w') {				if(tmpreg&0x7FF0000)					as_bad("Floating point register in register list");				insop(reverse_16_bits(tmpreg));			} else {				if(tmpreg&0x700FFFF)					as_bad("Wrong register in floating-point reglist");				install_operand(s[1],reverse_8_bits(tmpreg>>16));			}			break;		case 'L':			tmpreg=opP->reg;			if(s[1]=='w') {				if(tmpreg&0x7FF0000)					as_bad("Floating point register in register list");				insop(tmpreg);			} else if(s[1]=='8') {				if(tmpreg&0x0FFFFFF)					as_bad("incorrect register in reglist");				install_operand(s[1],tmpreg>>24);			} else {				if(tmpreg&0x700FFFF)					as_bad("wrong register in floating-point reglist");				else					install_operand(s[1],tmpreg>>16);			}			break;		case 'M':			install_operand(s[1],get_num(opP->con1,60));			break;		case 'O':			tmpreg= (opP->mode==DREG)				? 0x20+opP->reg-DATA				: (get_num(opP->con1,40)&0x1F);			install_operand(s[1],tmpreg);			break;		case 'Q':			tmpreg=get_num(opP->con1,10);			if(tmpreg==8)				tmpreg=0;			install_operand(s[1],tmpreg);			break;		case 'R':			/* This depends on the fact that ADDR registers are			   eight more than their corresponding DATA regs, so			   the result will have the ADDR_REG bit set */			install_operand(s[1],opP->reg-DATA);			break;		case 's':			if(opP->reg==FPI) tmpreg=0x1;			else if(opP->reg==FPS) tmpreg=0x2;			else if(opP->reg==FPC) tmpreg=0x4;			else abort();			install_operand(s[1],tmpreg);			break;		case 'S':	/* Ignore it */			break;		case 'T':			install_operand(s[1],get_num(opP->con1,30));			break;		case 'U':	/* Ignore it */			break;#ifdef m68851			/* JF: These are out of order, I fear. */		case 'f':			switch (opP->reg) {			case SFC:				tmpreg=0;				break;			case DFC:				tmpreg=1;				break;			default:				abort();			}			install_operand(s[1],tmpreg);			break;		case 'P':			switch(opP->reg) {			case TC:				tmpreg=0;				break;			case CAL:				tmpreg=4;				break;			case VAL:				tmpreg=5;				break;			case SCC:				tmpreg=6;				break;			case AC:				tmpreg=7;				break;			default:				abort();			}			install_operand(s[1],tmpreg);			break;		case 'V':			if (opP->reg == VAL)				break;			abort();		case 'W':			switch(opP->reg) {			case DRP:				tmpreg=1;				break;			case SRP:				tmpreg=2;				break;			case CRP:				tmpreg=3;				break;			default:				abort();			}			install_operand(s[1],tmpreg);			break;		case 'X':			switch (opP->reg) {			case BAD: case BAD+1: case BAD+2: case BAD+3:			case BAD+4: case BAD+5: case BAD+6: case BAD+7:				tmpreg = (4 << 10) | ((opP->reg - BAD) << 2);				break;			case BAC: case BAC+1: case BAC+2: case BAC+3:			case BAC+4: case BAC+5: case BAC+6: case BAC+7:				tmpreg = (5 << 10) | ((opP->reg - BAC) << 2);				break;			default:				abort();			}			install_operand(s[1], tmpreg);			break;		case 'Y':			if (opP->reg == PSR)				break;			abort();		case 'Z':			if (opP->reg == PCSR)				break;			abort();#endif /* m68851 */		default:			as_fatal("Internal error:  Operand type %c unknown",s[0]);		}	}	/* By the time whe get here (FINALLY) the_ins contains the complete	   instruction, ready to be emitted. . . */}intget_regs(i,str,opP)struct m68k_op *opP;char *str;{	/*			     26, 25, 24, 23-16,  15-8, 0-7 */	/* Low order 24 bits encoded fpc,fps,fpi,fp7-fp0,a7-a0,d7-d0 */	unsigned long int cur_regs = 0;	int	reg1,		reg2;#define ADD_REG(x)	{     if(x==FPI) cur_regs|=(1<<24);\			 else if(x==FPS) cur_regs|=(1<<25);\			 else if(x==FPC) cur_regs|=(1<<26);\			 else cur_regs|=(1<<(x-1));  }	reg1=i;	for(;;) {		if(*str=='/') {			ADD_REG(reg1);			str++;		} else if(*str=='-') {			str++;			reg2=m68k_reg_parse(&str);			if(reg2<DATA || reg2>=FPREG+8 || reg1==FPI || reg1==FPS || reg1==FPC) {				opP->error="unknown register in register list";				return FAIL;			}			while(reg1<=reg2) {				ADD_REG(reg1);				reg1++;			}			if(*str=='\0')				break;		} else if(*str=='\0') {			ADD_REG(reg1);			break;		} else {			opP->error="unknow character in register list";			return FAIL;		}/* DJA -- Bug Fix.  Did't handle d1-d2/a1 until the following instruction was added */		if (*str=='/')		  str ++;		reg1=m68k_reg_parse(&str);		if((reg1<DATA || reg1>=FPREG+8) && !(reg1==FPI || reg1==FPS || reg1==FPC)) {			opP->error="unknown register in register list";			return FAIL;		}	}	opP->reg=cur_regs;	return OK;}intreverse_16_bits(in)int in;{	int out=0;	int n;	static int mask[16] = {0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000	};	for(n=0;n<16;n++) {		if(in&mask[n])			out|=mask[15-n];	}	return out;}intreverse_8_bits(in)int in;{	int out=0;	int n;	static int mask[8] = {0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,	};	for(n=0;n<8;n++) {		if(in&mask[n])			out|=mask[7-n];	}	return out;}voidinstall_operand(mode,val)int mode;int val;{	switch(mode) {	case 's':		the_ins.opcode[0]|=val & 0xFF;	/* JF FF is for M kludge */		break;	case 'd':		the_ins.opcode[0]|=val<<9;		break;	case '1':		the_ins.opcode[1]|=val<<12;		break;	case '2':		the_ins.opcode[1]|=val<<6;		break;	case '3':		the_ins.opcode[1]|=val;		break;	case '4':		the_ins.opcode[2]|=val<<12;		break;	case '5':		the_ins.opcode[2]|=val<<6;		break;	case '6':			/* DANGER!  This is a hack to force cas2l and cas2w cmds			   to be three words long! */		the_ins.numo++;		the_ins.opcode[2]|=val;		break;	case '7':		the_ins.opcode[1]|=val<<7;		break;	case '8':		the_ins.opcode[1]|=val<<10;		break;#ifdef m68851	case '9':		the_ins.opcode[1]|=val<<5;		break;#endif	case 't':		the_ins.opcode[1]|=(val<<10)|(val<<7);		break;	case 'D':		the_ins.opcode[1]|=(val<<12)|val;		break;	case 'g':		the_ins.opcode[0]|=val=0xff;		break;	case 'i':		the_ins.opcode[0]|=val<<9;		break;	case 'C':		the_ins.opcode[1]|=val;		break;	case 'j':		the_ins.opcode[1]|=val;		the_ins.numo++;		/* What a hack */		break;	case 'k':		the_ins.opcode[1]|=val<<4;		break;	case 'b':	case 'w':	case 'l':		break;	case 'c':	default:		abort();	}}voidinstall_gen_operand(mode,val)int mode;int val;{	switch(mode) {	case 's':		the_ins.opcode[0]|=val;		break;	case 'd':			/* This is a kludge!!! */		the_ins.opcode[0]|=(val&0x07)<<9|(val&0x38)<<3;		break;	case 'b':	case 'w':	case 'l':	case 'f':	case 'F':	case 'x':	case 'p':		the_ins.opcode[0]|=val;		break;		/* more stuff goes here */	default:		abort();	}}char *crack_operand(str,opP)register char *str;register struct m68k_op *opP;{	register int parens;	register int c;	register char *beg_str;	if(!str) {		return str;	}	beg_str=str;	for(parens=0;*str && (parens>0 || notend(str));str++) {		if(*str=='(') parens++;		else if(*str==')') {			if(!parens) {		/* ERROR */				opP->error="Extra )";				return str;			}			--parens;		}	}

⌨️ 快捷键说明

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