aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1992-09-09 18:38:16 +0000
committerIan Lance Taylor <ian@airs.com>1992-09-09 18:38:16 +0000
commit3ad9ec6a7b491be1e1224861f31b351720fa1df0 (patch)
tree90c69136274493011976f4b512a566a8aecb0ab2
parentb53ccaacae4537af9cdc9b037f49f16467f84ea4 (diff)
downloadgdb-3ad9ec6a7b491be1e1224861f31b351720fa1df0.zip
gdb-3ad9ec6a7b491be1e1224861f31b351720fa1df0.tar.gz
gdb-3ad9ec6a7b491be1e1224861f31b351720fa1df0.tar.bz2
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.
-rw-r--r--gas/config/.Sanitize24
-rw-r--r--gas/config/ChangeLog18
-rw-r--r--gas/config/m68kcoff.mt3
-rw-r--r--gas/config/obj-coffbfd.c64
-rw-r--r--gas/config/obj-coffbfd.h7
-rw-r--r--gas/config/tc-m68k.c695
-rw-r--r--gas/config/tc-m68k.h30
7 files changed, 689 insertions, 152 deletions
diff --git a/gas/config/.Sanitize b/gas/config/.Sanitize
index 8781a69..6202795 100644
--- a/gas/config/.Sanitize
+++ b/gas/config/.Sanitize
@@ -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
diff --git a/gas/config/ChangeLog b/gas/config/ChangeLog
index 9f2f786..892cefa 100644
--- a/gas/config/ChangeLog
+++ b/gas/config/ChangeLog
@@ -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),
diff --git a/gas/config/m68kcoff.mt b/gas/config/m68kcoff.mt
new file mode 100644
index 0000000..97cee44
--- /dev/null
+++ b/gas/config/m68kcoff.mt
@@ -0,0 +1,3 @@
+TARG_CPU_DEPENDENTS=$(srcdir)/../include/opcode/m68k.h
+LOCAL_LOADLIBES=../bfd/libbfd.a
+TDEFINES=-DBFD_HEADERS -DMANY_SEGMENTS -DBFD -DM68KCOFF
diff --git a/gas/config/obj-coffbfd.c b/gas/config/obj-coffbfd.c
index 9bd17e3..dd194bb 100644
--- a/gas/config/obj-coffbfd.c
+++ b/gas/config/obj-coffbfd.c
@@ -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 */
diff --git a/gas/config/obj-coffbfd.h b/gas/config/obj-coffbfd.h
index c7ba3e7..b1b9a0b 100644
--- a/gas/config/obj-coffbfd.h
+++ b/gas/config/obj-coffbfd.h
@@ -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
diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c
index e243362..0342624 100644
--- a/gas/config/tc-m68k.c
+++ b/gas/config/tc-m68k.c
@@ -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,22 +860,233 @@ 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 '@' */
- opP->reg=i;
+#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=='\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;
+ 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;
/* 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
@@ -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 */
+
diff --git a/gas/config/tc-m68k.h b/gas/config/tc-m68k.h
index 0a7aa50..17f46e9 100644
--- a/gas/config/tc-m68k.h
+++ b/gas/config/tc-m68k.h
@@ -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 */