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

📄 m68k.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	if(!*str && parens) {		/* ERROR */		opP->error="Missing )";		return str;	}	c= *str;	*str='\0';	if(m68k_ip_op(beg_str,opP)==FAIL) {		*str=c;		return str;	}	*str=c;	if(c=='}')		c= *++str;		/* JF bitfield hack */	if(c) {		c= *++str;		if(!c)			as_bad("Missing operand");	}	return str;}/* See the comment up above where the #define notend(... is */#if 0notend(s)char *s;{	if(*s==',') return 0;	if(*s=='{' || *s=='}')		return 0;	if(*s!=':') return 1;		/* This kludge here is for the division cmd, which is a kludge */	if(index("aAdD#",s[1])) return 0;	return 1;}#endif/* This is the guts of the machine-dependent assembler.  STR points to a   machine dependent instruction.  This funciton is supposed to emit   the frags/bytes it assembles to. */voidmd_assemble(str)char *str;{	char *er;	short	*fromP;	char	*toP;	int	m,n;	char	*to_beg_P;	int	shorts_this_frag;	bzero((char *)(&the_ins),sizeof(the_ins));	/* JF for paranoia sake */	m68_ip(str);	er=the_ins.error;	if(!er) {		for(n=the_ins.numargs;n;--n)			if(the_ins.operands[n].error) {				er=the_ins.operands[n].error;				break;			}	}	if(er) {		as_bad("\"%s\" -- Statement '%s' ignored",er,str);		return;	}	if(the_ins.nfrag==0) {	/* No frag hacking involved; just put it out */		toP=frag_more(2*the_ins.numo);		fromP= &the_ins.opcode[0];		for(m=the_ins.numo;m;--m) {			md_number_to_chars(toP,(long)(*fromP),2);			toP+=2;			fromP++;		}			/* put out symbol-dependent info */		for(m=0;m<the_ins.nrel;m++) {			switch(the_ins.reloc[m].wid) {			case 'B':				n=1;				break;			case 'b':				n=1;				break;			case '3':				n=2;				break;			case 'w':				n=2;				break;			case 'l':				n=4;				break;			default:				as_fatal("Don't know how to figure width of %c in md_assemble()",the_ins.reloc[m].wid);			}			fix_new(frag_now,			    (toP-frag_now->fr_literal)-the_ins.numo*2+the_ins.reloc[m].n,			    n,			    the_ins.reloc[m].add,			    the_ins.reloc[m].sub,			    the_ins.reloc[m].off,			    the_ins.reloc[m].pcrel);		}		return;	}		/* There's some frag hacking */	for(n=0,fromP= &the_ins.opcode[0];n<the_ins.nfrag;n++) {		int wid;		if(n==0) wid=2*the_ins.fragb[n].fragoff;		else wid=2*(the_ins.numo-the_ins.fragb[n-1].fragoff);		toP=frag_more(wid);		to_beg_P=toP;		shorts_this_frag=0;		for(m=wid/2;m;--m) {			md_number_to_chars(toP,(long)(*fromP),2);			toP+=2;			fromP++;			shorts_this_frag++;		}		for(m=0;m<the_ins.nrel;m++) {			if((the_ins.reloc[m].n)>= 2*shorts_this_frag /* 2*the_ins.fragb[n].fragoff */) {				the_ins.reloc[m].n-= 2*shorts_this_frag /* 2*the_ins.fragb[n].fragoff */;				break;			}			wid=the_ins.reloc[m].wid;			if(wid==0)				continue;			the_ins.reloc[m].wid=0;			wid = (wid=='b') ? 1 : (wid=='w') ? 2 : (wid=='l') ? 4 : 4000;			fix_new(frag_now,			    (toP-frag_now->fr_literal)-the_ins.numo*2+the_ins.reloc[m].n,			    wid,			    the_ins.reloc[m].add,			    the_ins.reloc[m].sub,			    the_ins.reloc[m].off,			    the_ins.reloc[m].pcrel);		}		know(the_ins.fragb[n].fadd);		(void)frag_var(rs_machine_dependent,10,0,(relax_substateT)(the_ins.fragb[n].fragty), the_ins.fragb[n].fadd,the_ins.fragb[n].foff,to_beg_P);	}	n=(the_ins.numo-the_ins.fragb[n-1].fragoff);	shorts_this_frag=0;	if(n) {		toP=frag_more(n*sizeof(short));		while(n--) {			md_number_to_chars(toP,(long)(*fromP),2);			toP+=2;			fromP++;			shorts_this_frag++;		}	}	for(m=0;m<the_ins.nrel;m++) {		int wid;		wid=the_ins.reloc[m].wid;		if(wid==0)			continue;		the_ins.reloc[m].wid=0;		wid = (wid=='b') ? 1 : (wid=='w') ? 2 : (wid=='l') ? 4 : 4000;		fix_new(frag_now,		    (the_ins.reloc[m].n + toP-frag_now->fr_literal)-/* the_ins.numo */ shorts_this_frag*2,		    wid,		    the_ins.reloc[m].add,		    the_ins.reloc[m].sub,		    the_ins.reloc[m].off,		    the_ins.reloc[m].pcrel);	}}/* This function is called once, at assembler startup time.  This should   set up all the tables, etc that the MD part of the assembler needs */voidmd_begin(){/* * md_begin -- set up hash tables with 68000 instructions. * similar to what the vax assembler does.  ---phr */	/* RMS claims the thing to do is take the m68k-opcode.h table, and make	   a copy of it at runtime, adding in the information we want but isn't	   there.  I think it'd be better to have an awk script hack the table	   at compile time.  Or even just xstr the table and use it as-is.  But	   my lord ghod hath spoken, so we do it this way.  Excuse the ugly var	   names.  */	register struct m68k_opcode *ins;	register struct m68_incant *hack,		*slak;	register char *retval = 0;		/* empty string, or error msg text */	register int i;	register char c;	if ((op_hash = hash_new()) == NULL)		as_fatal("Virtual memory exhausted");	obstack_begin(&robyn,4000);	for (ins = m68k_opcodes; ins < endop; ins++) {		hack=slak=(struct m68_incant *)obstack_alloc(&robyn,sizeof(struct m68_incant));		do {			slak->m_operands=ins->args;			slak->m_opnum=strlen(slak->m_operands)/2;			slak->m_opcode=ins->opcode;				/* This is kludgey */			slak->m_codenum=((ins->match)&0xffffL) ? 2 : 1;			if((ins+1)!=endop && !strcmp(ins->name,(ins+1)->name)) {				slak->m_next=(struct m68_incant *)obstack_alloc(&robyn,sizeof(struct m68_incant));				ins++;			} else				slak->m_next=0;			slak=slak->m_next;		} while(slak);		retval = hash_insert (op_hash, ins->name,(char *)hack);			/* Didn't his mommy tell him about null pointers? */		if(retval && *retval)			as_fatal("Internal Error:  Can't hash %s: %s",ins->name,retval);	}	for (i = 0; i < sizeof(mklower_table) ; i++)		mklower_table[i] = (isupper(c = (char) i)) ? tolower(c) : c;	for (i = 0 ; i < sizeof(notend_table) ; i++) {		notend_table[i] = 0;		alt_notend_table[i] = 0;	}	notend_table[','] = 1;	notend_table['{'] = 1;	notend_table['}'] = 1;	alt_notend_table['a'] = 1;	alt_notend_table['A'] = 1;	alt_notend_table['d'] = 1;	alt_notend_table['D'] = 1;	alt_notend_table['#'] = 1;	alt_notend_table['f'] = 1;	alt_notend_table['F'] = 1;#ifdef REGISTER_PREFIX	alt_notend_table[REGISTER_PREFIX] = 1;#endif}#if 0#define notend(s) ((*s == ',' || *s == '}' || *s == '{' \                   || (*s == ':' && index("aAdD#", s[1]))) \               ? 0 : 1)#endif/* This funciton is called once, before the assembler exits.  It is   supposed to do any final cleanup for this part of the assembler. */voidmd_end(){}/* Equal to MAX_PRECISION in atof-ieee.c */#define MAX_LITTLENUMS 6/* Turn a string in input_line_pointer into a floating point constant of type   type, and store the appropriate bytes in *litP.  The number of LITTLENUMS   emitted is stored in *sizeP .  An error message is returned, or NULL on OK. */char *md_atof(type,litP,sizeP)char type;char *litP;int *sizeP;{	int	prec;	LITTLENUM_TYPE words[MAX_LITTLENUMS];	LITTLENUM_TYPE *wordP;	char	*t;	char	*atof_ieee();	switch(type) {	case 'f':	case 'F':	case 's':	case 'S':		prec = 2;		break;	case 'd':	case 'D':	case 'r':	case 'R':		prec = 4;		break;	case 'x':	case 'X':		prec = 6;		break;	case 'p':	case 'P':		prec = 6;		break;	default:		*sizeP=0;		return "Bad call to MD_ATOF()";	}	t=atof_ieee(input_line_pointer,type,words);	if(t)		input_line_pointer=t;	*sizeP=prec * sizeof(LITTLENUM_TYPE);	for(wordP=words;prec--;) {		md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));		litP+=sizeof(LITTLENUM_TYPE);	}	return "";	/* Someone should teach Dean about null pointers */}/* Turn an integer of n bytes (in val) into a stream of bytes appropriate   for use in the a.out file, and stores them in the array pointed to by buf.   This knows about the endian-ness of the target machine and does   THE RIGHT THING, whatever it is.  Possible values for n are 1 (byte)   2 (short) and 4 (long)  Floating numbers are put out as a series of   LITTLENUMS (shorts, here at least) */voidmd_number_to_chars(buf,val,n)char	*buf;long	val;int n;{	switch(n) {	case 1:		*buf++=val;		break;	case 2:		*buf++=(val>>8);		*buf++=val;		break;	case 4:		*buf++=(val>>24);		*buf++=(val>>16);		*buf++=(val>>8);		*buf++=val;		break;	default:		abort();	}}voidmd_number_to_imm(buf,val,n)char *buf;long val;int n;{	switch(n) {	case 1:		*buf++=val;		break;	case 2:		*buf++=(val>>8);		*buf++=val;		break;	case 4:		*buf++=(val>>24);		*buf++=(val>>16);		*buf++=(val>>8);		*buf++=val;		break;	default:		abort();	}}voidmd_number_to_disp(buf,val,n)char	*buf;long	val;int n;{	abort();}voidmd_number_to_field(buf,val,fix)char *buf;long val;void *fix;{	abort();}/* *fragP has been relaxed to its final size, and now needs to have   the bytes inside it modified to conform to the new size  There is UGLY   MAGIC here. .. */voidmd_convert_frag(fragP)register fragS *fragP;{  long disp;  long ext;  /* Address in gas core of the place to store the displacement.  */  register char *buffer_address = fragP -> fr_fix + fragP -> fr_literal;  /* Address in object code of the displacement.  */  register int object_address = fragP -> fr_fix + fragP -> fr_address;  know(fragP->fr_symbol);  /* The displacement of the address, from current location.  */  disp = (fragP->fr_symbol->sy_value + fragP->fr_offset) - object_address;  switch(fragP->fr_subtype) {  case TAB(BCC68000,BYTE):  case TAB(BRANCH,BYTE):    know(issbyte(disp));    if(disp==0)      as_bad("short branch with zero offset: use :w");    fragP->fr_opcode[1]=disp;    ext=0;    break;  case TAB(DBCC,SHORT):    know(issword(disp));    ext=2;    break;  case TAB(BCC68000,SHORT):  case TAB(BRANCH,SHORT):    know(issword(disp));    fragP->fr_opcode[1]=0x00;    ext=2;    break;  case TAB(BRANCH,LONG):    if(flagseen['m']) {      if(fragP->fr_opcode[0]==0x61) {	fragP->fr_opcode[0]= 0x4E;	fragP->fr_opcode[1]= 0xB9;	/* JBSR with ABSL LONG offset */	subseg_change(SEG_TEXT, 0);	fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset, 0);	fragP->fr_fix+=4;	ext=0;      } else if(fragP->fr_opcode[0]==0x60) {        fragP->fr_opcode[0]= 0x4E;        fragP->fr_opcode[1]= 0xF9;      /* JMP  with ABSL LONG offset */        subseg_change(SEG_TEXT, 0);        fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset,0);        fragP->fr_fix+=4;        ext=0;      }else {        as_bad("Long branch offset not supported.");      }    } else {      fragP->fr_opcode[1]=0xff;      ext=4;    }    break;  case TAB(BCC68000,LONG):	/* only Bcc 68000 instructions can come here */        /* change bcc into b!cc/jmp absl long */	fragP->fr_opcode[0] ^= 0x01; /* invert bcc */        fragP->fr_opcode[1] = 0x6;   /* branch offset = 6 */	/* JF: these used to be fr_opcode[2,3], but they may be in a	   different frag, in which case refering to them is a no-no.	   Only fr_opcode[0,1] are guaranteed to work. */        *buffer_address++ = 0x4e;  /* put in jmp long (0x4ef9) */         *buffer_address++ = 0xf9;          fragP->fr_fix += 2;	     /* account for jmp instruction */        subseg_change(SEG_TEXT,0);        fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, 					 fragP->fr_offset,0);        fragP->fr_fix += 4;        ext=0;	break;  case TAB(DBCC,LONG):        /* only DBcc 68000 instructions can come here */        /* change dbcc into dbcc/jmp absl long */	/* JF: these used to be fr_opcode[2-7], but that's wrong */        *buffer_address++ = 0x00;  /* branch offset = 4 */        *buffer_address++ = 0x04;          *buffer_address++ = 0x60;  /* put in bra pc+6 */         *buffer_address++ = 0x06;          *buffer_address++ = 0x4e;  /* put in jmp long (0x4ef9) */         *buffer_address++ = 0xf9;          fragP->fr_fix += 6;	     /* account for bra/jmp instructions */        subseg_change(SEG_TEXT,0);        fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, 					 fragP->fr_offset,0);        fragP->fr_fix += 4;        ext=0;    break;  case TAB(FBRANCH,SHORT):    know((fragP->fr_opcode[1]&0x40)==0);    ext=2;    break;  case TAB(FBRANCH,LONG):    fragP->fr_opcode[1]|=0x40;	/* Turn on LONG bit */    ext=4;    break;  case TAB(PCREL,SHORT):    ext=2;    break;  case TAB(PCREL,LONG):    /* The thing to do here is force it to ABSOLUTE LONG, since       PCREL is really trying to shorten an ABSOLUTE address anyway */    /* JF FOO This code has not been tested */    subseg_change(SEG_TEXT,0);    fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset, 0);    if((fragP->fr_opcode[1] & 0x3F) != 0x3A)  	as_bad("Internal error (long PC-relative operand) for insn 0x%04lx at 0x%lx",	        fragP->fr_opcode[0],fragP->fr_address);    fragP->fr_opcode[1]&= ~0x3F;    fragP->fr_opcode[1]|=0x39;	/* Mode 7.1 */    fragP->fr_fix+=4;    /* md_number_to_chars(buffer_address,		       (long)(fragP->fr_symbol->sy_value + fragP->fr_offset),		       4); */    ext=0;    break;  case TAB(PCLEA,SHORT):    subseg_change(SEG_TEXT,0);    fix_new(fragP,(int)(fragP->fr_fix),2,fragP->fr_symbol,(symbolS *)0,fragP->fr_offset,1);    fragP->fr_opcode[1] &= ~0x3F;    fragP->fr_opcode[1] |= 0x3A;    ext=2;    break;  case TAB(PCLEA,LONG):    subseg_change(SEG_TEXT,0);    fix_new(fragP,(int)(fragP->fr_fix)+2,4,fragP->fr_symbol,(symbolS *)0,fragP->fr_offset+2,1);    *buffer_address++ = 0x01;    *buffer_address++ = 0x70;    fragP->fr_fix+=2;    /* buffer_address+=2; */    ext=4;    break;  }  if(ext) {    md_number_to_chars(buffer_address,(long)disp,(int)ext);    fragP->fr_fix+=ext;  }}/* Force truly undefined symbols to their maximum size, and generally set up   the frag list to be relaxed */intmd_estimate_size_before_relax(fragP,segtype)register fragS *fragP;int segtype;{	int	old_fix;	register char *buffer_address = fragP -> fr_fix + fragP -> fr_literal;	old_fix=fragP->fr_fix;	/* handle SZ_UNDEF first, it can be changed to BYTE or SHORT */	switch(fragP->fr_subtype) {	case TAB(BRANCH,SZ_UNDEF):		if((fragP->fr_symbol->sy_type&N_TYPE)==segtype) {			fragP->fr_subtype=TAB(TABTYPE(fragP->fr_subtype),BYTE);			break;		} else if(flagseen['m']) {			if(fragP->fr_opcode[0]==0x61) {				if(flagseen['l']) {					fragP->fr_opcode[0]= 0x4E;					fragP->fr_opcode[1]= 0xB8;	/* JBSR with ABSL WORD offset */					subseg_change(SEG_TEXT, 0);					fix_new(fragP, fragP->fr_fix, 2, 						fragP->fr_symbol, 0, fragP->fr_offset, 0);					fragP->fr_fix+=2;				} 

⌨️ 快捷键说明

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