Wed Sep 9 11:10:24 1992 Ian Lance Taylor (ian@cygnus.com)

* tc-m68k.c (m68k_ip, m68k_ip_op, get_num, try_moto_index): merge
	 Motorola and MIT syntax; gas can now assemble either type of
	 file.
	tc-m68kmote.c, tc-m68kmote.h: removed now superfluous files.
	From Steve Chamberlain:
	m68kcoff.mt: for m68k COFF.
	obj-coffbfd.c: (fixup_mdeps) added
	 (size_section) removed bad sanity check
	 (fill_section) added rs_machine_dependent case
	 (write_object_file) call fixup_mdeps
	 (fixup_segment) set fx_subsy to 0.
	obj-coffbfd.h: define WORKING_DOT_WORD (too hard to support) and
	 handle m68k.
	tc-m68k.c, config/tc-m68k.h: added m68k COFF support and Motorala
	 pseudo ops.
This commit is contained in:
Ian Lance Taylor 1992-09-09 18:38:16 +00:00
parent b53ccaacae
commit 3ad9ec6a7b
7 changed files with 690 additions and 153 deletions

View File

@ -53,6 +53,7 @@ ho-sysv.h
ho-vax.h
i386aix.mt
m68k.mt
m68kcoff.mt
m88k-opcode.h
m88k.patches
mh-i386
@ -95,8 +96,6 @@ tc-i960.h
tc-m68851.h
tc-m68k.c
tc-m68k.h
tc-m68kmote.c
tc-m68kmote.h
tc-m88k.c
tc-m88k.h
tc-mips.c
@ -142,7 +141,26 @@ echo Done in `pwd`.
#
#
# $Log$
# Revision 1.26 1992/08/31 00:27:23 wilson
# Revision 1.27 1992/09/09 18:38:05 ian
# Wed Sep 9 11:10:24 1992 Ian Lance Taylor (ian@cygnus.com)
#
# * tc-m68k.c (m68k_ip, m68k_ip_op, get_num, try_moto_index): merge
# Motorola and MIT syntax; gas can now assemble either type of
# file.
# tc-m68kmote.c, tc-m68kmote.h: removed now superfluous files.
# From Steve Chamberlain:
# m68kcoff.mt: for m68k COFF.
# obj-coffbfd.c: (fixup_mdeps) added
# (size_section) removed bad sanity check
# (fill_section) added rs_machine_dependent case
# (write_object_file) call fixup_mdeps
# (fixup_segment) set fx_subsy to 0.
# obj-coffbfd.h: define WORKING_DOT_WORD (too hard to support) and
# handle m68k.
# tc-m68k.c, config/tc-m68k.h: added m68k COFF support and Motorala
# pseudo ops.
#
# Revision 1.26 1992/08/31 00:27:23 wilson
# Keep sparc.mt.
#
# Revision 1.25 1992/08/31 00:01:22 wilson

View File

@ -1,3 +1,21 @@
Wed Sep 9 11:10:24 1992 Ian Lance Taylor (ian@cygnus.com)
* tc-m68k.c (m68k_ip, m68k_ip_op, get_num, try_moto_index): merge
Motorola and MIT syntax; gas can now assemble either type of
file.
tc-m68kmote.c, tc-m68kmote.h: removed now superfluous files.
From Steve Chamberlain:
m68kcoff.mt: for m68k COFF.
obj-coffbfd.c: (fixup_mdeps) added
(size_section) removed bad sanity check
(fill_section) added rs_machine_dependent case
(write_object_file) call fixup_mdeps
(fixup_segment) set fx_subsy to 0.
obj-coffbfd.h: define WORKING_DOT_WORD (too hard to support) and
handle m68k.
tc-m68k.c, config/tc-m68k.h: added m68k COFF support and Motorala
pseudo ops.
Fri Aug 28 16:25:22 1992 Ian Lance Taylor (ian@cygnus.com)
* obj-bout.h, obj-bout.c (obj_header_append, obj_symbol_to_chars),

3
gas/config/m68kcoff.mt Normal file
View File

@ -0,0 +1,3 @@
TARG_CPU_DEPENDENTS=$(srcdir)/../include/opcode/m68k.h
LOCAL_LOADLIBES=../bfd/libbfd.a
TDEFINES=-DBFD_HEADERS -DMANY_SEGMENTS -DBFD -DM68KCOFF

View File

@ -97,6 +97,10 @@ void EXFUN(bfd_as_write_hook,(struct internal_filehdr *,
static void EXFUN(fixup_segment,(fixS * fixP,
segT this_segment_type));
static void EXFUN(fixup_mdeps,(fragS *));
static void EXFUN(fill_section,(bfd *abfd ,
struct internal_filehdr *f, unsigned
long *));
@ -135,7 +139,7 @@ static void EXFUN( obj_coff_size,(void));
static void EXFUN( obj_coff_tag,(void));
static void EXFUN( obj_coff_type,(void));
static void EXFUN( obj_coff_val,(void));
static void EXFUN( obj_coff_section,(void));
void EXFUN( obj_coff_section,(void));
static void EXFUN( tag_init,(void));
static void EXFUN( tag_insert,(char *name, symbolS *symbolP));
@ -253,27 +257,38 @@ symbolS* x)
/* calculate the size of the frag chain and fill in the section header
to contain all of it, also fill in the addr of the sections */
static unsigned int DEFUN(size_section,(abfd, idx),
bfd *abfd AND
unsigned int idx)
static unsigned int
DEFUN(size_section,(abfd, idx),
bfd *abfd AND
unsigned int idx)
{
unsigned int size = 0;
fragS *frag = segment_info[idx].frchainP->frch_root;
while (frag) {
size = frag->fr_address;
#if 0
if (frag->fr_address != size) {
printf("Out of step\n");
size = frag->fr_address;
}
size += frag->fr_fix;
switch (frag->fr_type) {
#ifdef TC_COFF_SIZEMACHDEP
case rs_machine_dependent:
size += TC_COFF_SIZEMACHDEP(frag);
break;
#endif
case rs_fill:
case rs_org:
size += frag->fr_fix;
size += frag->fr_offset * frag->fr_var;
break;
case rs_align:
size += frag->fr_fix;
size += relax_align(size, frag->fr_offset);
}
#endif
frag = frag->fr_next;
}
segment_info[idx].scnhdr.s_size = size;
@ -478,7 +493,16 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
while (frag) {
unsigned int fill_size;
switch (frag->fr_type) {
case rs_machine_dependent:
if(frag->fr_fix)
{
memcpy(buffer + frag->fr_address,
frag->fr_literal,
frag->fr_fix);
offset += frag->fr_fix;
}
break;
case rs_fill:
case rs_align:
case rs_org:
@ -507,6 +531,8 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
}
break;
case rs_broken_word:
break;
default:
abort();
}
@ -1703,7 +1729,8 @@ extern void DEFUN_VOID(write_object_file)
#ifndef TC_H8300
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
{
fixup_segment(segment_info[i].fix_root, i);
fixup_mdeps(segment_info[i].frchainP->frch_root);
fixup_segment(segment_info[i].fix_root, i);
}
#endif
@ -1781,7 +1808,7 @@ static void DEFUN(change_to_section,(name, len, exp),
subseg_new(i, exp);
}
static void
void
DEFUN_VOID(obj_coff_section)
{
/* Strip out the section name */
@ -2045,7 +2072,29 @@ static void DEFUN_VOID(obj_coff_lcomm)
demand_empty_rest_of_line();
}
static void DEFUN(fixup_mdeps,(frags),
fragS *frags)
{
while (frags)
{
switch (frags->fr_type)
{
case rs_align:
case rs_org:
frags->fr_type = rs_fill;
frags->fr_offset =
(frags->fr_next->fr_address - frags->fr_address - frags->fr_fix);
break;
case rs_machine_dependent:
md_convert_frag(0, frags);
break;
default:
;
}
frags = frags->fr_next;
}
}
#if 1
static void DEFUN(fixup_segment,(fixP, this_segment_type),
register fixS * fixP AND
@ -2100,6 +2149,7 @@ segT this_segment_type)
} /* not absolute */
add_number -= S_GET_VALUE(sub_symbolP);
fixP->fx_subsy = 0;
/* if sub_symbol is in the same segment that add_symbol
and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */

View File

@ -22,6 +22,8 @@
#define OBJ_COFF 1
#define WORKING_DOT_WORD
#include "targ-cpu.h"
#include "bfd.h"
@ -39,6 +41,10 @@
#elif defined(TC_H8300)
#include "coff/h8300.h"
#define TARGET_FORMAT "coff-h8300"
#elif defined(TC_M68K)
#include "coff/m68k.h"
#define TARGET_FORMAT "coff-m68k"
#elif defined(TC_A29K)
#include "coff/a29k.h"
#define TARGET_FORMAT "coff-a29k-big"
@ -93,7 +99,6 @@ help me
#ifndef FILE_HEADER_MAGIC
#define FILE_HEADER_MAGIC SIPFBOMAGIC
#endif /* FILE_HEADER_MAGIC */
#else
you lose
#endif

View File

@ -22,11 +22,13 @@
#include <ctype.h>
#define NO_RELOC 0
#include "as.h"
#include "read.h"
#include "obstack.h"
/* note that this file includes real declarations and thus can only be included by one source file per executable. */
#include "opcode/m68k.h"
#ifdef TE_SUN
/* This variable contains the value to write out at the beginning of
the a.out file. The 2<<16 means that this is a 68020 file instead
@ -76,8 +78,8 @@ static struct obstack robyn;
#define SHORT 1
#define LONG 2
#define SZ_UNDEF 3
#define BRANCH 1
#undef BRANCH
#define ABRANCH 1
#define FBRANCH 2
#define PCREL 3
#define BCC68000 4
@ -383,6 +385,8 @@ struct m68k_incant {
struct m68k_incant *m_next;
};
#define getone(x) ((((x)->m_opcode)>>16)&0xffff)
#define gettwo(x) (((x)->m_opcode)&0xffff)
@ -397,7 +401,7 @@ static int reverse_8_bits(int in);
static int try_index(char **s, struct m68k_op *opP);
static void install_gen_operand(int mode, int val);
static void install_operand(int mode, int val);
void s_bss(void);
static void s_bss(void);
static void s_data1(void);
static void s_data2(void);
static void s_even(void);
@ -413,7 +417,7 @@ static int reverse_8_bits();
static int try_index();
static void install_gen_operand();
static void install_operand();
void s_bss();
static void s_bss();
void s_align_bytes();
static void s_data1();
static void s_data2();
@ -446,8 +450,8 @@ const relax_typeS
{ 1, 1, 0, 0 }, /* that the VAX doesn't either */
{ 1, 1, 0, 0 },
{ (127), (-128), 0, TAB(BRANCH,SHORT)},
{ (32767), (-32768), 2, TAB(BRANCH,LONG) },
{ (127), (-128), 0, TAB(ABRANCH,SHORT)},
{ (32767), (-32768), 2, TAB(ABRANCH,LONG) },
{ 0, 0, 4, 0 },
{ 1, 1, 0, 0 },
@ -503,6 +507,33 @@ const pseudo_typeS md_pseudo_table[] = {
};
/* The mote pseudo ops are put into the opcode table, since they
don't start with a . they look like opcodes to gas.
*/
extern void obj_coff_section();
const pseudo_typeS mote_pseudo_table[] =
{
{ "dc.l", cons,4},
{ "dc", cons,2},
{ "dc.w", cons,2},
{ "dc.b", cons,1},
{ "ds.l", s_space,4},
{ "ds", s_space,2},
{ "ds.w", s_space,2},
{ "ds.b", s_space,1},
{ "xdef", s_globl, 0},
{ "align", s_align_ptwo, 0},
#ifdef M68KCOFF
{ "sect", obj_coff_section,0},
{ "section", obj_coff_section,0},
#endif
0,
};
/* #define isbyte(x) ((x)>=-128 && (x)<=127) */
/* #define isword(x) ((x)>=-32768 && (x)<=32767) */
@ -557,7 +588,12 @@ register char **ccp;
char *p = start;
symbolS *symbolP;
while (is_part_of_name(c = *p++))
c = *p++;
while (isalpha(c) || isdigit(c))
{
c = *p++;
}
;
* -- p = 0;
symbolP = symbol_find(start);
@ -575,18 +611,175 @@ register char **ccp;
}
#define SKIP_WHITE() { str++; if(*str==' ') str++;}
#define SKIP_W() { ss++; if(*ss==' ') ss++;}
/* Parse an index specification using Motorola syntax. */
static int
try_moto_index(s,opP)
char **s;
struct m68k_op *opP;
{
register int i;
char *ss;
ss= *s;
/* SKIP_W(); */
if(*ss==' ') ss++;
i=m68k_reg_parse(&ss);
if(!(i>=DATA+0 && i<=ADDR+7)) { /* if i is not DATA or ADDR reg */
opP->error="Invalid index register";
*s=ss;
return FAIL;
}
opP->ireg=i;
/* SKIP_W(); */
if(*ss==')') {
opP->isiz=0;
opP->imul=1;
SKIP_W();
*s=ss;
return OK;
}
if(*ss!='.') {
opP->error="Missing . in index register";
*s=ss;
return FAIL;
}
SKIP_W();
if(mklower(*ss)=='w') opP->isiz=2;
else if(mklower(*ss)=='l') opP->isiz=3;
else {
opP->error="Size spec not .W or .L";
*s=ss;
return FAIL;
}
SKIP_W();
if(*ss=='.' || *ss=='*') {
SKIP_W();
switch(*ss) {
case '1':
case '2':
case '4':
case '8':
opP->imul= *ss-'0';
break;
default:
opP->error="index multiplier not 1, 2, 4 or 8";
*s=ss;
return FAIL;
}
SKIP_W();
} else opP->imul=1;
if(*ss!=')') {
opP->error="Missing )";
*s=ss;
return FAIL;
}
SKIP_W();
*s=ss;
return OK;
}
/*
* m68k_ip_op := '#' + <anything>
* | <register> + range_sep + get_regs
*
* try_index := data_or_address_register + ')' + SKIP_W
* | data_or_address_register + ':' + SKIP_W + size_spec + SKIP_W + multiplier + ')' + SKIP_W
*
* multiplier := <empty>
* | ':' + multiplier_number
* ;
*
* range_sep := '/' | '-' ;
* multiplier_number := '1' | '2' | '4' | '8' ;
*
* SKIP_WHITE := <empty> | ' ' ;
* size_spec := 'l' | 'L' | 'w' | 'W' ;
*
* SKIP_W := <empty> | ' ' ;
*
*/
static int try_index(s,opP)
char **s;
struct m68k_op *opP;
{
register int i;
char *ss;
ss= *s;
/* SKIP_W(); */
i=m68k_reg_parse(&ss);
if(!(i>=DATA+0 && i<=ADDR+7)) { /* if i is not DATA or ADDR reg */
*s=ss;
return FAIL;
}
opP->ireg=i;
/* SKIP_W(); */
if(*ss==')') {
opP->isiz=0;
opP->imul=1;
SKIP_W();
*s=ss;
return OK;
}
if(*ss!=':') {
opP->error="Missing : in index register";
*s=ss;
return FAIL;
}
SKIP_W();
switch(*ss) {
case 'w':
case 'W':
opP->isiz=2;
break;
case 'l':
case 'L':
opP->isiz=3;
break;
default:
opP->error="Index register size spec not :w or :l";
*s=ss;
return FAIL;
}
SKIP_W();
if(*ss==':') {
SKIP_W();
switch(*ss) {
case '1':
case '2':
case '4':
case '8':
if (cpu_of_arch(current_architecture) < m68020) {
opP->error="no index scaling in pre-68020's";
*s=ss;
return FAIL;
}
opP->imul= *ss-'0';
break;
default:
opP->error="index multiplier not 1, 2, 4 or 8";
*s=ss;
return FAIL;
}
SKIP_W();
} else opP->imul=1;
if(*ss!=')') {
opP->error="Missing )";
*s=ss;
return FAIL;
}
SKIP_W();
*s=ss;
return OK;
} /* try_index() */
/* Ian Taylor expanded this function to accept both MIT and Motorola
syntax. I removed the old comment, since it was wrong. The syntax
this accepted even before my changes was complex and undocumented.
I mainly added a large case when the operand string does not
contain an '@', since the Motorola syntax does not use the '@'
character. */
int
m68k_ip_op(str,opP)
char *str;
@ -596,6 +789,7 @@ register struct m68k_op *opP;
long i;
char *parse_index();
int needp;
if (*str==' ') {
str++;
} /* Find the beginning of the string */
@ -605,8 +799,8 @@ register struct m68k_op *opP;
return FAIL;
} /* Out of gas */
for(strend = str; *strend; strend++) ;;
for(strend = str; *strend; strend++)
;
--strend;
if(*str=='#') {
@ -618,16 +812,29 @@ register struct m68k_op *opP;
i = m68k_reg_parse(&str);
/* is a register, is exactly a register, and is followed by '@' */
if (i!=FAIL) {
if(*str=='/' || *str=='-') {
/* "Rm-Rn/Ro-Rp" Register list for MOVEM instruction */
opP->mode=REGLST;
return get_regs(i,str,opP);
}
if(*str=='\0') {
opP->reg=i;
/* "Rn" Register Direct mode */
if(i>=DATA+0 && i<=DATA+7)
opP->mode=DREG;
else if(i>=ADDR+0 && i<=ADDR+7)
opP->mode=AREG;
else
opP->mode=MSCR;
return OK;
}
}
if((i==FAIL || *str!='\0') && *str!='@') {
if (*str!='@') {
char *stmp;
if(i!=FAIL && (*str=='/' || *str=='-')) {
opP->mode=REGLST;
return(get_regs(i,str,opP));
}
if ((stmp=strchr(str,'@')) != '\0') {
if ((stmp=strchr(str,'@')) != 0) {
opP->con1=add_exp(str,stmp-1);
if(stmp==strend) {
opP->mode=AINDX;
@ -653,23 +860,234 @@ register struct m68k_op *opP;
}
return(OK);
} /* if there's an '@' */
opP->mode = ABSL;
opP->con1 = add_exp(str,strend);
return(OK);
} /* not a register, not exactly a register, or no '@' */
#ifndef MIT_SYNTAX_ONLY
/* The operand has no '@'. Try to parse it using
Motorola syntax. */
/* Logic of the parsing switch(*str):
case opP->mode =
---- -----------
#anything IMMED 1
REG AREG or DREG or MSCR 3 or 2 or 13
REG- or REG/ REGLST 14
(REG) AINDR 4
(REG)+ AINC 6
(REG,INDX) AINDX 8
(EXPR,REG) AOFF 7
(EXPR,REG,INDX) AINDX 8
-(REG) ADEC 5
EXP2(REG) AOFF 7
EXP2(REG,INDX) AINDX 8
EXP2 ABSL 12
REG means truth(m68k_reg_parse(&str))
INDX means truth(try_moto_index(&str,opP))
EXPR means not REG
EXP2 means not REG and not '(' and not '-('
*/
if(*str=='(') {
str++;
i=m68k_reg_parse(&str);
if((i<ADDR+0 || i>ADDR+7)
&& (i<DATA+0 || i>DATA+7
|| *str != ')' || str[1] != '0')
&& i!=PC && i!=ZPC && i!=FAIL) {
/* Can't indirect off non address regs */
opP->error="Invalid indirect register";
return FAIL;
}
if(i!=FAIL) {
opP->reg=i;
if(*str==')') {
str++;
if(*str=='\0') {
/* "(An)" Address Register Indirect mode
or "(Dn)" for cas2. */
if (i>=DATA+0 && i<=DATA+7)
opP->mode=DINDR;
else
opP->mode=AINDR;
return OK;
}
if(*str=='+') {
if(str[1]=='\0') {
/* "(An)+" Register Indirect w Postincrement */
opP->mode=AINC;
return OK;
}
}
opP->error="Junk after indirect";
return FAIL;
}
if(*str==',') {
str++;
i=try_moto_index(&str,opP);
if(i==FAIL) return FAIL;
/* "(An,Rn)" Register Indirect with Index mode*/
opP->mode=AINDX;
return OK;
}
else {
opP->error="Bad indirect syntax";
return FAIL;
}
}
else {
/* "(EXPR,..." , a displacement */
char *stmp;
char *index();
if(stmp=index(str,',')) {
opP->con1=add_exp(str,stmp-1);
str=stmp;
SKIP_WHITE();
i=m68k_reg_parse(&str);
if((i<ADDR+0 || i>ADDR+7) && i!=PC && i!=ZPC) {
/* Can't indirect off non address regs */
opP->error="Invalid indirect register";
return FAIL;
}
if(i!=FAIL) {
opP->reg=i;
if(*str==')') {
/* "(d,An)" Register Indirect w Displacement */
opP->mode=AOFF;
return OK;
}
if(*str==',') {
str++;
i=try_moto_index(&str,opP);
if(i==FAIL) return FAIL;
/* "(d,An,Rn)" Register Indirect with Index */
opP->mode=AINDX;
return OK;
}
else {
opP->error="Bad indirect syntax";
return FAIL;
}
}
else {
opP->error="Invalid register";
return FAIL;
}
}
else {
opP->mode = ABSL;
opP->con1 = add_exp(str-1,strend);
return OK;
}
}
}
if(*str=='-') {
if(str[1]=='(') {
str = str+2;
i=m68k_reg_parse(&str);
if((i<ADDR+0 || i>ADDR+7) && i!=PC && i!=ZPC && i!=FAIL) {
/* Can't indirect off non address regs */
opP->error="Invalid indirect register";
return FAIL;
}
if(i!=FAIL) {
opP->reg=i;
if(*str==')') {
str++;
if(*str=='\0') {
/* "-(An)" Register Indirect with Predecrement */
opP->mode=ADEC;
return OK;
}
opP->error="Junk after indirect";
return FAIL;
}
opP->error="Bad indirect syntax";
return FAIL;
}
opP->mode = ABSL;
opP->con1 = add_exp(str-2,strend);
return OK;
}
/* if '-' but not "-(', do nothing */
}
/* whether *str=='-' or not */
{
/* "EXP2" or "EXP2(REG..." */
char *stmp;
char *index();
if(stmp=index(str,'(')) {
char *ostr=str;
opP->con1=add_exp(str,stmp-1);
str=stmp+1;
i=m68k_reg_parse(&str);
if((i<ADDR+0 || i>ADDR+7) && i!=PC
&& i!=ZPC && i!=FAIL) {
/* Can't indirect off non address regs */
opP->error="Invalid indirect register";
return FAIL;
}
if(i!=FAIL) {
opP->reg=i;
if(*str==')') {
/* "d(An)" Register Indirect w Displacement */
opP->mode=AOFF;
return OK;
}
if(*str==',') {
str++;
i=try_moto_index(&str,opP);
if(i==FAIL) return FAIL;
/* "d(An,Rn)" Register Indirect with Index */
opP->mode=AINDX;
return OK;
}
else {
opP->error="Bad indirect syntax";
return FAIL;
}
}
else {
opP->mode = ABSL;
opP->con1 = add_exp(ostr,strend);
return OK;
}
}
else {
/* "EXP2" Absolute */
opP->mode=ABSL;
opP->isiz=0;
if(strend[-1]=='.' || strend[-1]==':') {
/* mode ==foo.[wl] */
switch(*strend) {
case 'w':
case 'W':
opP->isiz=2;
strend-=2;
break;
case 'l':
case 'L':
opP->isiz=3;
strend-=2;
break;
}
}
opP->con1=add_exp(str,strend);
return OK;
}
}
/*NOTREACHED*/
#else /* defined (MIT_SYNTAX_ONLY) */
opP->mode=ABSL;
opP->con1=add_exp(str,strend);
return OK;
#endif /* defined (MIT_SYNTAX_ONLY) */
}
opP->reg=i;
if (*str=='\0') {
if(i>=DATA+0 && i<=DATA+7)
opP->mode=DREG;
else if(i>=ADDR+0 && i<=ADDR+7)
opP->mode=AREG;
else
opP->mode=MSCR;
return OK;
}
/* Can't indirect off non address regs, but Dx@ is OK for cas2 */
if((i<ADDR+0 || i>ADDR+7) && i!=PC && i!=ZPC && i!=FAIL
&& (str[1] != '\0' || i<DATA+0 || i>DATA+7)) {
@ -681,7 +1099,7 @@ register struct m68k_op *opP;
str++;
switch(*str) {
case '\0':
if (i < DATA + 0 || i > DATA + 7)
if (i<DATA+0 || i>DATA+7)
opP->mode=AINDR;
else
opP->mode=DINDR;
@ -837,98 +1255,24 @@ register struct m68k_op *opP;
return(OK);
} /* m68k_ip_op() */
/*
*
* try_index := data_or_address_register + ')' + SKIP_W
* | data_or_address_register + ':' + SKIP_W + size_spec + SKIP_W + multiplier + ')' + SKIP_W
*
* multiplier := <empty>
* | ':' + multiplier_number
* ;
*
* multiplier_number := '1' | '2' | '4' | '8' ;
*
* size_spec := 'l' | 'L' | 'w' | 'W' ;
*
* SKIP_W := <empty> | ' ' ;
*
*/
static int try_index(s,opP)
char **s;
struct m68k_op *opP;
#ifdef M68KCOFF
short tc_coff_fix2rtype(fixP)
fixS *fixP;
{
register int i;
char *ss;
#define SKIP_W() { ss++; if (*ss==' ') ss++;}
return (fixP->fx_pcrel ?
(fixP->fx_size == 1 ? R_PCRBYTE :
fixP->fx_size == 2 ? R_PCRWORD :
R_PCRLONG):
(fixP->fx_size == 1 ? R_RELBYTE :
fixP->fx_size == 2 ? R_RELWORD :
R_RELLONG));
ss= *s;
/* SKIP_W(); */
i=m68k_reg_parse(&ss);
if(!(i>=DATA+0 && i<=ADDR+7)) { /* if i is not DATA or ADDR reg */
*s=ss;
return FAIL;
}
opP->ireg=i;
/* SKIP_W(); */
if(*ss==')') {
opP->isiz=0;
opP->imul=1;
SKIP_W();
*s=ss;
return OK;
}
if(*ss!=':') {
opP->error="Missing : in index register";
*s=ss;
return FAIL;
}
SKIP_W();
switch(*ss) {
case 'w':
case 'W':
opP->isiz=2;
break;
case 'l':
case 'L':
opP->isiz=3;
break;
default:
opP->error="Index register size spec not :w or :l";
*s=ss;
return FAIL;
}
SKIP_W();
if(*ss==':') {
SKIP_W();
switch(*ss) {
case '1':
case '2':
case '4':
case '8':
if (cpu_of_arch(current_architecture) < m68020) {
opP->error="no index scaling in pre-68020's";
*s=ss;
return FAIL;
}
opP->imul= *ss-'0';
break;
default:
opP->error="index multiplier not 1, 2, 4 or 8";
*s=ss;
return FAIL;
}
SKIP_W();
} else opP->imul=1;
if(*ss!=')') {
opP->error="Missing )";
*s=ss;
return FAIL;
}
SKIP_W();
*s=ss;
return OK;
} /* try_index() */
}
#endif
#ifdef TEST1 /* TEST1 tests m68k_ip_op(), which parses operands */
main()
@ -995,6 +1339,7 @@ void m68k_ip (instring)
register struct m68k_incant *opcode;
register char *s;
register int tmpreg = 0, baseo = 0, outro = 0, nextword;
char *pdot, *pdotmove;
int siz1, siz2;
char c;
int losing;
@ -1009,10 +1354,13 @@ void m68k_ip (instring)
/* Scan up to end of operation-code, which MUST end in end-of-string
or exactly 1 space. */
for (p = instring; *p != '\0'; p++)
pdot = 0;
for (p = instring; *p != '\0'; p++) {
if (*p == ' ')
break;
if (*p == '.')
pdot = p;
}
if (p == instring) {
the_ins.error = "No operator";
@ -1023,12 +1371,26 @@ void m68k_ip (instring)
/* p now points to the end of the opcode name, probably whitespace.
make sure the name is null terminated by clobbering the whitespace,
look it up in the hash table, then fix it back. */
look it up in the hash table, then fix it back.
Remove a dot, first, since the opcode tables have none. */
if (pdot != NULL) {
for (pdotmove=pdot; pdotmove<p; pdotmove++)
*pdotmove=pdotmove[1];
p--;
}
c = *p;
*p = '\0';
opcode = (struct m68k_incant *)hash_find (op_hash, instring);
*p = c;
if (pdot != NULL) {
for (pdotmove=p; pdotmove>pdot; pdotmove--)
*pdotmove=pdotmove[-1];
*pdot='.';
++p;
}
if (opcode == NULL) {
the_ins.error = "Unknown operator";
the_ins.opcode[0] = NULL;
@ -1039,6 +1401,20 @@ void m68k_ip (instring)
/* found a legitimate opcode, start matching operands */
while (*p == ' ') ++p;
if (opcode->m_operands == 0) {
char *old = input_line_pointer;
*old = '\n';
input_line_pointer = p;
/* Ahh - it's a motorola style psuedo op */
mote_pseudo_table[opcode->m_opnum].poc_handler
( mote_pseudo_table[opcode->m_opnum].poc_val);
input_line_pointer = old;
*old = 0;
return;
}
for(opP = &the_ins.operands[0]; *p; opP++) {
p = crack_operand(p, opP);
@ -1959,7 +2335,7 @@ void m68k_ip (instring)
&& (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));
add_frag(adds(opP->con1),offs(opP->con1),TAB(ABRANCH,SZ_UNDEF));
}
break;
case 'w':
@ -2280,6 +2656,7 @@ void m68k_ip (instring)
s[0], __LINE__, __FILE__);
}
}
/* By the time whe get here (FINALLY) the_ins contains the complete
instruction, ready to be emitted. . . */
} /* m68k_ip() */
@ -2899,8 +3276,6 @@ md_assemble(str)
void
md_begin()
{
@ -2949,7 +3324,7 @@ void
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);
as_bad("Internal Error: Can't hash %s: %s",ins->name,retval);
}
for (i = 0; i < sizeof(mklower_table) ; i++)
@ -2973,6 +3348,24 @@ void
alt_notend_table[REGISTER_PREFIX] = 1;
#endif
#ifndef MIT_SYNTAX_ONLY
/* Insert pseudo ops, these have to go into the opcode table since
gas expects pseudo ops to start with a dot */
{
int n = 0;
while (mote_pseudo_table[n].poc_name)
{
hack=(struct m68k_incant *)
obstack_alloc(&robyn,sizeof(struct m68k_incant));
hash_insert(op_hash,
mote_pseudo_table[n].poc_name, (char *)hack);
hack->m_operands = 0;
hack->m_opnum = n;
n++;
}
}
#endif
init_regtable();
}
@ -3142,7 +3535,7 @@ register fragS *fragP;
switch(fragP->fr_subtype) {
case TAB(BCC68000,BYTE):
case TAB(BRANCH,BYTE):
case TAB(ABRANCH,BYTE):
know(issbyte(disp));
if(disp==0)
as_bad("short branch with zero offset: use :w");
@ -3154,12 +3547,12 @@ register fragS *fragP;
ext=2;
break;
case TAB(BCC68000,SHORT):
case TAB(BRANCH,SHORT):
case TAB(ABRANCH,SHORT):
know(issword(disp));
fragP->fr_opcode[1]=0x00;
ext=2;
break;
case TAB(BRANCH,LONG):
case TAB(ABRANCH,LONG):
if (cpu_of_arch(current_architecture) < m68020) {
if (fragP->fr_opcode[0]==0x61) {
fragP->fr_opcode[0]= 0x4E;
@ -3304,7 +3697,7 @@ segT segment;
/* handle SZ_UNDEF first, it can be changed to BYTE or SHORT */
switch (fragP->fr_subtype) {
case TAB(BRANCH,SZ_UNDEF): {
case TAB(ABRANCH,SZ_UNDEF): {
if((fragP->fr_symbol != NULL) /* Not absolute */
&& S_GET_SEGMENT(fragP->fr_symbol) == segment) {
fragP->fr_subtype=TAB(TABTYPE(fragP->fr_subtype),BYTE);
@ -3341,7 +3734,7 @@ segT segment;
}
break;
} /* case TAB(BRANCH,SZ_UNDEF) */
} /* case TAB(ABRANCH,SZ_UNDEF) */
case TAB(FBRANCH,SZ_UNDEF): {
if(S_GET_SEGMENT(fragP->fr_symbol) == segment || flagseen['l']) {
@ -3459,7 +3852,7 @@ segT segment;
/* now that SZ_UNDEF are taken care of, check others */
switch (fragP->fr_subtype) {
case TAB(BCC68000,BYTE):
case TAB(BRANCH,BYTE):
case TAB(ABRANCH,BYTE):
/* We can't do a short jump to the next instruction,
so we force word mode. */
if (fragP->fr_symbol && S_GET_VALUE(fragP->fr_symbol)==0 &&
@ -3630,26 +4023,31 @@ int ok;
}
exp->e_siz=0;
if(/* ok!=80 && */exp->e_end[-1]==':' && (exp->e_end-exp->e_beg)>=2) {
if(/* ok!=80 && */ (exp->e_end[-1]==':' || exp->e_end[-1]=='.')
&& (exp->e_end-exp->e_beg)>=2) {
switch(exp->e_end[0]) {
case 's':
case 'S':
case 'b':
case 'B':
exp->e_siz=1;
exp->e_end-=2;
break;
case 'w':
case 'W':
exp->e_siz=2;
exp->e_end-=2;
break;
case 'l':
case 'L':
exp->e_siz=3;
exp->e_end-=2;
break;
default:
as_bad("Unknown size for expression \"%c\"",exp->e_end[0]);
if (exp->e_end[-1] == ':')
as_bad("Unknown size for expression \"%c\"",exp->e_end[0]);
break;
}
exp->e_end-=2;
}
c_save=exp->e_end[1];
exp->e_end[1]='\0';
@ -4081,6 +4479,24 @@ fixS *fixP;
return(fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address);
}
void
tc_coff_symbol_emit_hook ()
{
}
int
tc_coff_sizemachdep(frag)
fragS *frag;
{
switch (frag->fr_subtype & 0x3)
{
case BYTE: return 1;
case SHORT: return 2;
case LONG: return 4;
default: abort();
}
}
/*
* Local Variables:
* comment-column: 0
@ -4089,3 +4505,4 @@ fixS *fixP;
*/
/* end of tc-m68k.c */

View File

@ -1,3 +1,23 @@
/* This file is tc-m68k.h
Copyright (C) 1987-1992 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GAS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* This file is tp-generic.h and is intended to be a template for
* target processor specific header files.
@ -5,6 +25,14 @@
#define TC_M68K 1
#define COFF_MAGIC MC68MAGIC
#define BFD_ARCH bfd_arch_m68k
#define COFF_FLAGS F_AR32W
#define TC_COUNT_RELOC(x) ((x)->fx_addsy||(x)->fx_subsy||(x)->fx_offset)
#define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype(fixP)
#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag)
#ifdef TE_SUN3
/* This variable contains the value to write out at the beginning of
the a.out file. The 2<<16 means that this is a 68020 file instead
@ -14,8 +42,6 @@
#endif /* TE_SUN3 */
#define AOUT_MACHTYPE 0x2
#define REVERSE_SORT_RELOCS /* FIXME-NOW: this line can be removed. */
#define LOCAL_LABELS_FB
#define tc_crawl_symbol_chain(a) {;} /* not used */
#define tc_headers_hook(a) {;} /* not used */