aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorK. Richard Pixley <rich@cygnus>1991-10-16 04:19:14 +0000
committerK. Richard Pixley <rich@cygnus>1991-10-16 04:19:14 +0000
commit7c15cbe8146ec86f08af38cb522cccf41d705a60 (patch)
tree74042a46eca431304cd319b0abf76034859c93f8 /gas
parent93ae2e889a7077982241cb07986f8a2993b5dfb7 (diff)
downloadgdb-7c15cbe8146ec86f08af38cb522cccf41d705a60.zip
gdb-7c15cbe8146ec86f08af38cb522cccf41d705a60.tar.gz
gdb-7c15cbe8146ec86f08af38cb522cccf41d705a60.tar.bz2
typo in a comment.
Diffstat (limited to 'gas')
-rw-r--r--gas/config/tc-m68k.c1837
1 files changed, 983 insertions, 854 deletions
diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c
index 63cd802..3b9f7dc 100644
--- a/gas/config/tc-m68k.c
+++ b/gas/config/tc-m68k.c
@@ -160,11 +160,120 @@ struct m68k_exp {
short e_siz; /* 0== default 1==short/byte 2==word 3==long */
};
+/* DATA and ADDR have to be contiguous, so that reg-DATA gives 0-7==data reg,
+ 8-15==addr reg for operands that take both types */
+
+enum _register {
+ DATA = 1, /* 1- 8 == data registers 0-7 */
+ DATA0 = DATA,
+ DATA1,
+ DATA2,
+ DATA3,
+ DATA4,
+ DATA5,
+ DATA6,
+ DATA7,
+
+ ADDR,
+ ADDR0 = ADDR,
+ ADDR1,
+ ADDR2,
+ ADDR3,
+ ADDR4,
+ ADDR5,
+ ADDR6,
+ ADDR7,
+
+/* Note that COPNUM==processor #1 -- COPNUM+7==#8, which stores as 000 */
+/* I think. . . */
+
+ SP = ADDR7,
+
+ FPREG, /* Eight FP registers */
+ FP0 = FPREG,
+ FP1,
+ FP2,
+ FP3,
+ FP4,
+ FP5,
+ FP6,
+ FP7,
+ COPNUM = (FPREG+8), /* Co-processor #1-#8 */
+ COP0 = COPNUM,
+ COP1,
+ COP2,
+ COP3,
+ COP4,
+ COP5,
+ COP6,
+ COP7,
+ PC, /* Program counter */
+ ZPC, /* Hack for Program space, but 0 addressing */
+ SR, /* Status Reg */
+ CCR, /* Condition code Reg */
+
+/* These have to be in order for the movec instruction to work. */
+ USP, /* User Stack Pointer */
+ ISP, /* Interrupt stack pointer */
+ SFC,
+ DFC,
+ CACR,
+ VBR,
+ CAAR,
+ MSP,
+ ITT0,
+ ITT1,
+ DTT0,
+ DTT1,
+ MMUSR,
+ TC,
+ SRP,
+ URP,
+/* end of movec ordering constraints */
+
+ FPI,
+ FPS,
+ FPC,
+
+ DRP,
+ CRP,
+ CAL,
+ VAL,
+ SCC,
+ AC,
+ BAD,
+ BAD0 = BAD,
+ BAD1,
+ BAD2,
+ BAD3,
+ BAD4,
+ BAD5,
+ BAD6,
+ BAD7,
+ BAC,
+ BAC0 = BAC,
+ BAC1,
+ BAC2,
+ BAC3,
+ BAC4,
+ BAC5,
+ BAC6,
+ BAC7,
+ PSR,
+ PCSR,
+
+ IC, /* instruction cache token */
+ DC, /* data cache token */
+ NC, /* no cache token */
+ BC, /* both caches token */
+
+};
+
/* Internal form of an operand. */
struct m68k_op {
char *error; /* Couldn't parse it */
enum operand_type mode; /* What mode this instruction is in. */
- unsigned long reg; /* Base register */
+ enum _register reg; /* Base register */
struct m68k_exp *con1;
int ireg; /* Index register */
int isiz; /* 0==unspec 1==byte(?) 2==short 3==long */
@@ -173,7 +282,7 @@ struct m68k_op {
};
/* internal form of a 68020 instruction */
-struct m68_it {
+struct m68k_it {
char *error;
char *args; /* list of opcode info */
int numargs;
@@ -205,10 +314,10 @@ struct m68_it {
} reloc[5]; /* Five is enough??? */
};
-struct m68_it the_ins; /* the instruction being assembled */
-
+static struct m68k_it the_ins; /* the instruction being assembled */
+static enum m68k_architecture max_arch_this_insn;
-/* Macros for adding things to the m68_it struct */
+/* Macros for adding things to the m68k_it struct */
#define addword(w) the_ins.opcode[the_ins.numo++]=(w)
@@ -256,12 +365,13 @@ struct m68_it the_ins; /* the instruction being assembled */
#define offs(exp) ((exp)->e_exp.X_add_number)
-struct m68_incant {
+struct m68k_incant {
char *m_operands;
unsigned long m_opcode;
short m_opnum;
short m_codenum;
- struct m68_incant *m_next;
+ enum m68k_architecture m_arch;
+ struct m68k_incant *m_next;
};
#define getone(x) ((((x)->m_opcode)>>16)&0xffff)
@@ -302,6 +412,15 @@ static void s_proc();
#endif /* __STDC__ */
+static enum m68k_architecture current_architecture = m68020
+#ifndef NO_68881
+ | m68881
+#endif
+#ifndef NO_68851
+ | m68851
+#endif
+ ;
+
/* BCC68000 is for patching in an extra jmp instruction for long offsets
on the 68000. The 68000 doesn't support long branches with branchs */
@@ -392,59 +511,10 @@ const pseudo_typeS md_pseudo_table[] = {
extern char *input_line_pointer;
-#define FAIL 0
-#define OK 1
-
-/* DATA and ADDR have to be contiguous, so that reg-DATA gives 0-7==data reg,
- 8-15==addr reg for operands that take both types */
-#define DATA 1 /* 1- 8 == data registers 0-7 */
-#define ADDR (DATA+8) /* 9-16 == address regs 0-7 */
-#define FPREG (ADDR+8) /* 17-24 Eight FP registers */
-#define COPNUM (FPREG+8) /* 25-32 Co-processor #1-#8 */
-
-#define PC (COPNUM+8) /* 33 Program counter */
-#define ZPC (PC+1) /* 34 Hack for Program space, but 0 addressing */
-#define SR (ZPC+1) /* 35 Status Reg */
-#define CCR (SR+1) /* 36 Condition code Reg */
-
-/* These have to be in order for the movec instruction to work. */
-#define USP (CCR+1) /* 37 User Stack Pointer */
-#define ISP (USP+1) /* 38 Interrupt stack pointer */
-#define SFC (ISP+1) /* 39 */
-#define DFC (SFC+1) /* 40 */
-#define CACR (DFC+1) /* 41 */
-#define VBR (CACR+1) /* 42 */
-#define CAAR (VBR+1) /* 43 */
-#define MSP (CAAR+1) /* 44 */
-
-#define FPI (MSP+1) /* 45 */
-#define FPS (FPI+1) /* 46 */
-#define FPC (FPS+1) /* 47 */
-/*
- * these defines should be in m68k.c but
- * i put them here to keep all the m68851 stuff
- * together -rab
- * JF--Make sure these #s don't clash with the ones in m68k.c
- * That would be BAD.
- */
-#define TC (FPC+1) /* 48 */
-#define DRP (TC+1) /* 49 */
-#define SRP (DRP+1) /* 50 */
-#define CRP (SRP+1) /* 51 */
-#define CAL (CRP+1) /* 52 */
-#define VAL (CAL+1) /* 53 */
-#define SCC (VAL+1) /* 54 */
-#define AC (SCC+1) /* 55 */
-#define BAD (AC+1) /* 56,57,58,59, 60,61,62,63 */
-#define BAC (BAD+8) /* 64,65,66,67, 68,69,70,71 */
-#define PSR (BAC+8) /* 72 */
-#define PCSR (PSR+1) /* 73 */
-
-
-/* Note that COPNUM==processor #1 -- COPNUM+7==#8, which stores as 000 */
-/* I think. . . */
-
-#define SP ADDR+7
+enum {
+ FAIL = 0,
+ OK = 1,
+};
/* JF these tables here are for speed at the expense of size */
/* You can replace them with the #if 0 versions if you really
@@ -465,136 +535,167 @@ static char alt_notend_table[256];
/* JF modified this to handle cases where the first part of a symbol name
looks like a register */
-int
-m68k_reg_parse(ccp)
+/*
+ * m68k_reg_parse() := if it looks like a register, return it's token &
+ * advance the pointer.
+ */
+
+enum _register m68k_reg_parse(ccp)
register char **ccp;
{
- register char c1,
- c2,
- c3,
- c4;
+#ifndef MAX_REG_NAME_LEN
+#define MAX_REG_NAME_LEN (6)
+#endif /* MAX_REG_NAME_LEN */
+ register char c[MAX_REG_NAME_LEN];
+ char *p, *q;
register int n = 0,
ret = FAIL;
- c1=mklower(ccp[0][0]);
+ c[0] = mklower(ccp[0][0]);
#ifdef REGISTER_PREFIX
- if(c1!=REGISTER_PREFIX)
- return FAIL;
- c1=mklower(ccp[0][1]);
- c2=mklower(ccp[0][2]);
- c3=mklower(ccp[0][3]);
- c4=mklower(ccp[0][4]);
-#else
- c2=mklower(ccp[0][1]);
- c3=mklower(ccp[0][2]);
- c4=mklower(ccp[0][3]);
+ if (c[0] != REGISTER_PREFIX) {
+ return(FAIL);
+ } /* need prefix */
#endif
- switch(c1) {
+
+ for (p = c, q = ccp[0]; p < c + MAX_REG_NAME_LEN && *q != 0; ++p, ++q) {
+ *p = mklower(*q);
+ } /* downcase */
+
+ switch(c[0]) {
case 'a':
- if(c2>='0' && c2<='7') {
+ if(c[1]>='0' && c[1]<='7') {
n=2;
- ret=ADDR+c2-'0';
+ ret=ADDR+c[1]-'0';
}
-#ifdef m68851
- else if (c2 == 'c') {
+#ifndef NO_68851
+ else if (c[1] == 'c') {
n = 2;
ret = AC;
}
#endif
break;
-#ifdef m68851
+#ifndef NO_68851
case 'b':
- if (c2 == 'a') {
- if (c3 == 'd') {
- if (c4 >= '0' && c4 <= '7') {
+ if (c[1] == 'a') {
+ if (c[2] == 'd') {
+ if (c[3] >= '0' && c[3] <= '7') {
n = 4;
- ret = BAD + c4 - '0';
+ ret = BAD + c[3] - '0';
}
- }
- if (c3 == 'c') {
- if (c4 >= '0' && c4 <= '7') {
+ } /* BAD */
+ if (c[2] == 'c') {
+ if (c[3] >= '0' && c[3] <= '7') {
n = 4;
- ret = BAC + c4 - '0';
+ ret = BAC + c[3] - '0';
}
- }
- }
+ } /* BAC */
+ } else if (c[1] == 'c') {
+ n = 2;
+ ret = BC;
+ } /* BC */
break;
#endif
case 'c':
-#ifdef m68851
- if (c2 == 'a' && c3 == 'l') {
+#ifndef NO_68851
+ if (c[1] == 'a' && c[2] == 'l') {
n = 3;
ret = CAL;
} else
#endif
/* This supports both CCR and CC as the ccr reg. */
- if(c2=='c' && c3=='r') {
+ if(c[1]=='c' && c[2]=='r') {
n=3;
ret = CCR;
- } else if(c2=='c') {
+ } else if(c[1]=='c') {
n=2;
ret = CCR;
- } else if(c2=='a' && (c3=='a' || c3=='c') && c4=='r') {
+ } else if(c[1]=='a' && (c[2]=='a' || c[2]=='c') && c[3]=='r') {
n=4;
- ret = c3=='a' ? CAAR : CACR;
+ ret = c[2]=='a' ? CAAR : CACR;
}
-#ifdef m68851
- else if (c2 == 'r' && c3 == 'p') {
+#ifndef NO_68851
+ else if (c[1] == 'r' && c[2] == 'p') {
n = 3;
ret = (CRP);
}
#endif
break;
case 'd':
- if(c2>='0' && c2<='7') {
- n=2;
- ret = DATA+c2-'0';
- } else if(c2=='f' && c3=='c') {
- n=3;
+ if (c[1] >= '0' && c[1] <= '7') {
+ n = 2;
+ ret = DATA + c[1] - '0';
+ } else if (c[1] == 'f' && c[2] == 'c') {
+ n = 3;
ret = DFC;
+ } else if (c[1] == 'c') {
+ n = 2;
+ ret = DC;
+ } else if (c[1] == 't' && c[2] == 't') {
+ if ('0' <= c[3] && c[3] <= '1') {
+ n = 4;
+ ret = DTT0 + (c[3] - '0');
+ } /* DTT[01] */
}
-#ifdef m68851
- else if (c2 == 'r' && c3 == 'p') {
+#ifndef NO_68851
+ else if (c[1] == 'r' && c[2] == 'p') {
n = 3;
ret = (DRP);
}
#endif
break;
case 'f':
- if(c2=='p') {
- if(c3>='0' && c3<='7') {
+ if(c[1]=='p') {
+ if(c[2]>='0' && c[2]<='7') {
n=3;
- ret = FPREG+c3-'0';
- if(c4==':')
+ ret = FPREG+c[2]-'0';
+ if(c[3]==':')
ccp[0][3]=',';
- } else if(c3=='i') {
+ } else if(c[2]=='i') {
n=3;
ret = FPI;
- } else if(c3=='s') {
- n= (c4 == 'r' ? 4 : 3);
+ } else if(c[2]=='s') {
+ n= (c[3] == 'r' ? 4 : 3);
ret = FPS;
- } else if(c3=='c') {
- n= (c4 == 'r' ? 4 : 3);
+ } else if(c[2]=='c') {
+ n= (c[3] == 'r' ? 4 : 3);
ret = FPC;
}
}
break;
case 'i':
- if(c2=='s' && c3=='p') {
- n=3;
+ if (c[1] == 's' && c[2] == 'p') {
+ n = 3;
ret = ISP;
+ } else if (c[1] == 'c') {
+ n = 2;
+ ret = IC;
+ } else if (c[1] == 't' && c[2] == 't') {
+ if ('0' <= c[3] && c[3] <= '1') {
+ n = 4;
+ ret = ITT0 + (c[3] - '0');
+ } /* ITT[01] */
}
break;
case 'm':
- if(c2=='s' && c3=='p') {
- n=3;
+ if (c[1] == 's' && c[2] == 'p') {
+ n = 3;
ret = MSP;
+ } else if (c[1] == 'm' && c[2] == 'u' && c[3] == 's' && c[4] == 'r') {
+ n = 5;
+ ret = MMUSR;
+ }
+ break;
+ case 'n':
+ if (c[1] == 'c') {
+ n = 2;
+ ret = NC;
}
break;
case 'p':
- if(c2=='c') {
-#ifdef m68851
- if(c3 == 's' && c4=='r') {
+ if(c[1]=='c') {
+#ifndef NO_68851
+ if(c[2] == 's' && c[3]=='r') {
n=4;
ret = (PCSR);
} else
@@ -604,62 +705,65 @@ register char **ccp;
ret = PC;
}
}
-#ifdef m68851
- else if (c2 == 's' && c3 == 'r') {
+#ifndef NO_68851
+ else if (c[1] == 's' && c[2] == 'r') {
n = 3;
ret = (PSR);
}
#endif
break;
case 's':
-#ifdef m68851
- if (c2 == 'c' && c3 == 'c') {
+#ifndef NO_68851
+ if (c[1] == 'c' && c[2] == 'c') {
n = 3;
ret = (SCC);
- } else if (c2 == 'r' && c3 == 'p') {
- n = 3;
- ret = (SRP);
- } else
+ } else
#endif
- if(c2=='r') {
- n=2;
- ret = SR;
- } else if(c2=='p') {
- n=2;
- ret = ADDR+7;
- } else if(c2=='f' && c3=='c') {
- n=3;
+ if (c[1] == 'r') {
+ if (c[2] == 'p') {
+ n = 3;
+ ret = SRP;
+ } else {
+ n = 2;
+ ret = SR;
+ } /* srp else sr */
+ } else if (c[1] == 'p') {
+ n = 2;
+ ret = SP;
+ } else if (c[1] == 'f' && c[2] == 'c') {
+ n = 3;
ret = SFC;
}
break;
-#ifdef m68851
case 't':
- if(c2 == 'c') {
- n=2;
- ret=TC;
+ if (c[1] == 'c') {
+ n = 2;
+ ret = TC;
}
break;
-#endif
case 'u':
- if(c2=='s' && c3=='p') {
+ if (c[1] == 's' && c[2] == 'p') {
n=3;
ret = USP;
+ } else if (c[1] == 'r' && c[2] == 'p') {
+ n = 3;
+ ret = URP;
}
break;
case 'v':
-#ifdef m68851
- if (c2 == 'a' && c3 == 'l') {
+#ifndef NO_68851
+ if (c[1] == 'a' && c[2] == 'l') {
n = 3;
ret = (VAL);
} else
#endif
- if(c2=='b' && c3=='r') {
+ if(c[1]=='b' && c[2]=='r') {
n=3;
ret = VBR;
}
break;
case 'z':
- if(c2=='p' && c3=='c') {
+ if(c[1]=='p' && c[2]=='c') {
n=3;
ret = ZPC;
}
@@ -682,6 +786,17 @@ register char **ccp;
#define SKIP_WHITE() { str++; if(*str==' ') str++;}
+/*
+ * m68k_ip_op := '#' + <anything>
+ * | <register> + range_sep + get_regs
+ * ;
+ *
+ * range_sep := '/' | '-' ;
+ *
+ * SKIP_WHITE := <empty> | ' ' ;
+ *
+ */
+
int
m68k_ip_op(str,opP)
char *str;
@@ -691,26 +806,30 @@ register struct m68k_op *opP;
long i;
char *parse_index();
- if(*str==' ')
+ if (*str==' ') {
str++;
- /* Find the end of the string */
+ } /* Find the beginning of the string */
+
if(!*str) {
- /* Out of gas */
opP->error="Missing operand";
return FAIL;
- }
- for(strend=str;*strend;strend++)
- ;
- --strend;
+ } /* Out of gas */
+
+ for(strend = str; *strend; strend++) ;;
- /* Guess what: A constant. Shar and enjoy */
+ --strend;
+
if(*str=='#') {
str++;
opP->con1=add_exp(str,strend);
opP->mode=IMMED;
return OK;
- }
- i=m68k_reg_parse(&str);
+ } /* Guess what: A constant. Shar and enjoy */
+
+ i = m68k_reg_parse(&str);
+
+ /* is a register, is exactly a register, and is followed by '@' */
+
if((i==FAIL || *str!='\0') && *str!='@') {
char *stmp;
@@ -731,16 +850,28 @@ register struct m68k_op *opP;
}
i=try_index(&stmp,opP);
opP->con2=add_exp(stmp,strend);
- if(i==FAIL) opP->mode=AMIND;
- else opP->mode=APODX;
+
+ if (i == FAIL) {
+ opP->mode=AMIND;
+ if (max_arch_this_insn < m68020) {
+ max_arch_this_insn = m68020;
+ } /* bump arch */
+ } else {
+ opP->mode=APODX;
+ if (max_arch_this_insn < m68020) {
+ max_arch_this_insn = m68020;
+ } /* bump arch */
+ }
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;
- if(*str=='\0') {
+
+ if (*str=='\0') {
if(i>=DATA+0 && i<=DATA+7)
opP->mode=DREG;
else if(i>=ADDR+0 && i<=ADDR+7)
@@ -749,6 +880,7 @@ register struct m68k_op *opP;
opP->mode=MSCR;
return OK;
}
+
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;
@@ -840,6 +972,11 @@ register struct m68k_op *opP;
str+=2;
if(opP->ireg!=FAIL) {
opP->mode=APRDX;
+
+ if (max_arch_this_insn < m68020) {
+ max_arch_this_insn = m68020;
+ } /* bump arch */
+
i=try_index(&str,opP);
if(i!=FAIL) {
opP->error="Two index registers! not allowed!";
@@ -847,7 +984,8 @@ register struct m68k_op *opP;
}
} else
i=try_index(&str,opP);
- if(i==FAIL) {
+
+ if (i == FAIL) {
char *beg_str;
beg_str=str;
@@ -873,12 +1011,29 @@ register struct m68k_op *opP;
return FAIL;
}
opP->mode=APODX;
- } else if(opP->ireg!=FAIL)
+ if (max_arch_this_insn < m68020) {
+ max_arch_this_insn = m68020;
+ } /* bump arch */
+ } else if(opP->ireg!=FAIL) {
opP->mode=APRDX;
- else
+
+ if (max_arch_this_insn < m68020) {
+ max_arch_this_insn = m68020;
+ } /* bump arch */
+ } else {
opP->mode=AMIND;
- } else
+
+ if (max_arch_this_insn < m68020) {
+ max_arch_this_insn = m68020;
+ } /* bump arch */
+ }
+ } else {
opP->mode=APODX;
+ if (max_arch_this_insn < m68020) {
+ max_arch_this_insn = m68020;
+ } /* bump arch */
+ }
+
if(*str!='\0') {
opP->error="Junk after indirect";
return FAIL;
@@ -886,13 +1041,30 @@ register struct m68k_op *opP;
return OK;
}
+/*
+ *
+ * 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;
{
register int i;
char *ss;
-#define SKIP_W() { ss++; if(*ss==' ') ss++;}
+#define SKIP_W() { ss++; if (*ss==' ') ss++;}
ss= *s;
/* SKIP_W(); */
@@ -985,12 +1157,12 @@ main()
static struct hash_control* op_hash = NULL; /* handle of the OPCODE hash table
- NULL means any use before m68_ip_begin()
+ NULL means any use before m68k_ip_begin()
will crash */
/*
- * m 6 8 _ i p ( )
+ * m 6 8 k _ i p ( )
*
* This converts a string into a 68k instruction.
* The string must be a bare single instruction in sun format
@@ -1009,387 +1181,446 @@ static struct hash_control* op_hash = NULL; /* handle of the OPCODE hash table
* No argument string should generate such an error string:
* it means a bug in our code, not in the user's text.
*
- * You MUST have called m68_ip_begin() once and m86_ip_end() never before using
+ * You MUST have called m68k_ip_begin() once and m86_ip_end() never before using
* this function.
*/
/* JF this function no longer returns a useful value. Sorry */
-void
-m68_ip (instring)
-char *instring;
+void m68k_ip (instring)
+char *instring;
{
register char *p;
register struct m68k_op *opP;
- register struct m68_incant *opcode;
+ register struct m68k_incant *opcode;
register char *s;
register int tmpreg = 0,
- baseo = 0,
- outro = 0,
- nextword;
+ baseo = 0,
+ outro = 0,
+ nextword;
int siz1,
- siz2;
+ siz2;
char c;
int losing;
int opsfound;
char *crack_operand();
LITTLENUM_TYPE words[6];
LITTLENUM_TYPE *wordp;
-
+
+ max_arch_this_insn = m68000;
+
if (*instring == ' ')
- instring++; /* skip leading whitespace */
-
- /* Scan up to end of operation-code, which MUST end in end-of-string
- or exactly 1 space. */
+ instring++; /* skip leading whitespace */
+
+ /* Scan up to end of operation-code, which MUST end in end-of-string
+ or exactly 1 space. */
for (p = instring; *p != '\0'; p++)
- if (*p == ' ')
- break;
-
-
+ if (*p == ' ')
+ break;
+
+
if (p == instring) {
the_ins.error = "No operator";
the_ins.opcode[0] = NULL;
/* the_ins.numo=1; */
return;
}
-
- /* 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. */
+
+ /* 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. */
c = *p;
*p = '\0';
- opcode = (struct m68_incant *)hash_find (op_hash, instring);
+ opcode = (struct m68k_incant *)hash_find (op_hash, instring);
*p = c;
-
+
if (opcode == NULL) {
the_ins.error = "Unknown operator";
the_ins.opcode[0] = NULL;
/* the_ins.numo=1; */
return;
}
-
- /* found a legitimate opcode, start matching operands */
+
+ /* found a legitimate opcode, start matching operands */
while (*p == ' ') ++p;
-
+
for(opP = &the_ins.operands[0]; *p; opP++) {
-
+
p = crack_operand(p, opP);
-
+
if (opP->error) {
the_ins.error=opP->error;
return;
}
}
-
+
opsfound=opP- &the_ins.operands[0];
+
/* This ugly hack is to support the floating pt opcodes in their standard form */
/* Essentially, we fake a first enty of type COP#1 */
- if(opcode->m_operands[0]=='I') {
+ if (opcode->m_operands[0]=='I') {
int n;
-
+
for(n=opsfound;n>0;--n)
- the_ins.operands[n]=the_ins.operands[n-1];
-
+ the_ins.operands[n]=the_ins.operands[n-1];
+
/* bcopy((char *)(&the_ins.operands[0]),(char *)(&the_ins.operands[1]),opsfound*sizeof(the_ins.operands[0])); */
bzero((char *)(&the_ins.operands[0]),sizeof(the_ins.operands[0]));
the_ins.operands[0].mode=MSCR;
the_ins.operands[0].reg=COPNUM; /* COP #1 */
opsfound++;
}
- /* We've got the operands. Find an opcode that'll
- accept them */
+
+ /* We've got the operands. Find an opcode that'll accept them */
for (losing = 0; ; ) {
- if (opsfound != opcode->m_opnum)
- losing++;
- else for (s=opcode->m_operands,opP= &the_ins.operands[0];*s && !losing;s+=2,opP++) {
+ /* if we didn't get the right number of ops, or either
+ the modes of our args or this op line itself are out
+ of order... */
+
+ if ((opsfound != opcode->m_opnum)
+ || ((max_arch_this_insn > current_architecture)
+ || (opcode->m_arch > current_architecture))) {
+ ++losing;
+
+ } else {
+ for (s=opcode->m_operands, opP = &the_ins.operands[0]; *s && !losing; s += 2, opP++) {
/* Warning: this switch is huge! */
/* I've tried to organize the cases into this order:
non-alpha first, then alpha by letter. lower-case goes directly
before uppercase counterpart. */
/* Code with multiple case ...: gets sorted by the lowest case ...
it belongs to. I hope this makes sense. */
- switch(*s) {
- case '!':
- if(opP->mode==MSCR || opP->mode==IMMED ||
- opP->mode==DREG || opP->mode==AREG || opP->mode==AINC || opP->mode==ADEC || opP->mode==REGLST)
- losing++;
- break;
-
- case '#':
- if(opP->mode!=IMMED)
- losing++;
- else {
- long t;
-
- t=get_num(opP->con1,80);
- if(s[1]=='b' && !isbyte(t))
- losing++;
- else if(s[1]=='w' && !isword(t))
+ switch(*s) {
+ case '!':
+ if(opP->mode==MSCR || opP->mode==IMMED ||
+ opP->mode==DREG || opP->mode==AREG || opP->mode==AINC || opP->mode==ADEC || opP->mode==REGLST)
+ losing++;
+ break;
+
+ case '#':
+ if(opP->mode!=IMMED)
+ losing++;
+ else {
+ long t;
+
+ t=get_num(opP->con1,80);
+ if(s[1]=='b' && !isbyte(t))
+ losing++;
+ else if(s[1]=='w' && !isword(t))
+ losing++;
+ }
+ break;
+
+ case '^':
+ case 'T':
+ if(opP->mode!=IMMED)
+ losing++;
+ break;
+
+ case '$':
+ if(opP->mode==MSCR || opP->mode==AREG ||
+ opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || opP->mode==REGLST)
+ losing++;
+ break;
+
+ case '%':
+ if(opP->mode==MSCR || opP->reg==PC ||
+ opP->reg==ZPC || opP->mode==REGLST)
+ losing++;
+ break;
+
+
+ case '&':
+ if(opP->mode==MSCR || opP->mode==DREG ||
+ opP->mode==AREG || opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC ||
+ opP->mode==AINC || opP->mode==ADEC || opP->mode==REGLST)
+ losing++;
+ break;
+
+ case '*':
+ if(opP->mode==MSCR || opP->mode==REGLST)
+ losing++;
+ break;
+
+ case '+':
+ if(opP->mode!=AINC)
+ losing++;
+ break;
+
+ case '-':
+ if(opP->mode!=ADEC)
+ losing++;
+ break;
+
+ case '/':
+ if(opP->mode==MSCR || opP->mode==AREG ||
+ opP->mode==AINC || opP->mode==ADEC || opP->mode==IMMED || opP->mode==REGLST)
+ losing++;
+ break;
+
+ case ';':
+ if(opP->mode==MSCR || opP->mode==AREG || opP->mode==REGLST)
+ losing++;
+ break;
+
+ case '?':
+ if(opP->mode==MSCR || opP->mode==AREG ||
+ opP->mode==AINC || opP->mode==ADEC || opP->mode==IMMED || opP->reg==PC ||
+ opP->reg==ZPC || opP->mode==REGLST)
+ losing++;
+ break;
+
+ case '@':
+ if(opP->mode==MSCR || opP->mode==AREG ||
+ opP->mode==IMMED || opP->mode==REGLST)
+ losing++;
+ break;
+
+ case '~': /* For now! (JF FOO is this right?) */
+ if(opP->mode==MSCR || opP->mode==DREG ||
+ opP->mode==AREG || opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || opP->mode==REGLST)
+ losing++;
+ break;
+
+ case 'A':
+ if(opP->mode!=AREG)
+ losing++;
+ break;
+ case 'a':
+ if (opP->mode != AINDR) {
+ ++losing;
+ } /* if not address register indirect */
+ break;
+ case 'B': /* FOO */
+ if(opP->mode!=ABSL || (flagseen['S'] && instring[0] == 'j'
+ && instring[1] == 'b'
+ && instring[2] == 's'
+ && instring[3] == 'r'))
+ losing++;
+ break;
+
+ case 'C':
+ if(opP->mode!=MSCR || opP->reg!=CCR)
+ losing++;
+ break;
+
+ case 'd': /* FOO This mode is a KLUDGE!! */
+ if(opP->mode!=AOFF && (opP->mode!=ABSL ||
+ opP->con1->e_beg[0]!='(' || opP->con1->e_end[0]!=')'))
+ losing++;
+ break;
+
+ case 'D':
+ if(opP->mode!=DREG)
+ losing++;
+ break;
+
+ case 'F':
+ if(opP->mode!=MSCR || opP->reg<(FPREG+0) || opP->reg>(FPREG+7))
+ losing++;
+ break;
+
+ case 'I':
+ if(opP->mode!=MSCR || opP->reg<COPNUM ||
+ opP->reg>=COPNUM+7)
+ losing++;
+ break;
+
+ case 'J':
+ if (opP->mode != MSCR
+ || opP->reg < USP
+ || opP->reg > URP
+ || (current_architecture & m68000up) < m68010 /* before 68010 had none */
+ || ((current_architecture & m68020up) == 0
+ && opP->reg != SFC
+ && opP->reg != DFC
+ && opP->reg != USP
+ && opP->reg != VBR) /* 68010's had only these */
+ || ((current_architecture & m68040) == 0
+ && opP->reg != SFC
+ && opP->reg != DFC
+ && opP->reg != USP
+ && opP->reg != VBR
+ && opP->reg != CACR
+ && opP->reg != CAAR
+ && opP->reg != MSP
+ && opP->reg != ISP) /* 680[23]0's have only these */
+ || ((current_architecture & m68040) /* 68040 has all but this */
+ && opP->reg == CAAR)) {
losing++;
- }
- break;
-
- case '^':
- case 'T':
- if(opP->mode!=IMMED)
- losing++;
- break;
-
- case '$':
- if(opP->mode==MSCR || opP->mode==AREG ||
- opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || opP->mode==REGLST)
- losing++;
- break;
-
- case '%':
- if(opP->mode==MSCR || opP->reg==PC ||
- opP->reg==ZPC || opP->mode==REGLST)
- losing++;
- break;
-
-
- case '&':
- if(opP->mode==MSCR || opP->mode==DREG ||
- opP->mode==AREG || opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC ||
- opP->mode==AINC || opP->mode==ADEC || opP->mode==REGLST)
- losing++;
- break;
-
- case '*':
- if(opP->mode==MSCR || opP->mode==REGLST)
- losing++;
- break;
-
- case '+':
- if(opP->mode!=AINC)
- losing++;
- break;
-
- case '-':
- if(opP->mode!=ADEC)
- losing++;
- break;
-
- case '/':
- if(opP->mode==MSCR || opP->mode==AREG ||
- opP->mode==AINC || opP->mode==ADEC || opP->mode==IMMED || opP->mode==REGLST)
- losing++;
- break;
-
- case ';':
- if(opP->mode==MSCR || opP->mode==AREG || opP->mode==REGLST)
- losing++;
- break;
-
- case '?':
- if(opP->mode==MSCR || opP->mode==AREG ||
- opP->mode==AINC || opP->mode==ADEC || opP->mode==IMMED || opP->reg==PC ||
- opP->reg==ZPC || opP->mode==REGLST)
- losing++;
- break;
-
- case '@':
- if(opP->mode==MSCR || opP->mode==AREG ||
- opP->mode==IMMED || opP->mode==REGLST)
- losing++;
- break;
-
- case '~': /* For now! (JF FOO is this right?) */
- if(opP->mode==MSCR || opP->mode==DREG ||
- opP->mode==AREG || opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || opP->mode==REGLST)
- losing++;
- break;
-
- case 'A':
- if(opP->mode!=AREG)
- losing++;
- break;
-
- case 'B': /* FOO */
- if(opP->mode!=ABSL || (flagseen['S'] && instring[0] == 'j'
- && instring[1] == 'b'
- && instring[2] == 's'
- && instring[3] == 'r'))
- losing++;
- break;
-
- case 'C':
- if(opP->mode!=MSCR || opP->reg!=CCR)
- losing++;
- break;
-
- case 'd': /* FOO This mode is a KLUDGE!! */
- if(opP->mode!=AOFF && (opP->mode!=ABSL ||
- opP->con1->e_beg[0]!='(' || opP->con1->e_end[0]!=')'))
- losing++;
- break;
-
- case 'D':
- if(opP->mode!=DREG)
- losing++;
- break;
-
- case 'F':
- if(opP->mode!=MSCR || opP->reg<(FPREG+0) || opP->reg>(FPREG+7))
- losing++;
- break;
-
- case 'I':
- if(opP->mode!=MSCR || opP->reg<COPNUM ||
- opP->reg>=COPNUM+7)
- losing++;
- break;
-
- case 'J':
- if(opP->mode!=MSCR || opP->reg<USP || opP->reg>MSP)
- losing++;
- break;
-
- case 'k':
- if(opP->mode!=IMMED)
- losing++;
- break;
-
- case 'l':
- case 'L':
- if(opP->mode==DREG || opP->mode==AREG || opP->mode==FPREG) {
- if(s[1]=='8')
+ } /* doesn't cut it */
+ break;
+
+ case 'k':
+ if(opP->mode!=IMMED)
+ losing++;
+ break;
+
+ case 'l':
+ case 'L':
+ if(opP->mode==DREG || opP->mode==AREG || opP->mode==FPREG) {
+ if(s[1]=='8')
+ losing++;
+ else {
+ opP->mode=REGLST;
+ opP->reg=1<<(opP->reg-DATA);
+ }
+ } else if(opP->mode!=REGLST) {
losing++;
+ } else if(s[1]=='8' && opP->reg&0x0FFffFF)
+ losing++;
+ else if(s[1]=='3' && opP->reg&0x7000000)
+ losing++;
+ break;
+
+ case 'M':
+ if(opP->mode!=IMMED)
+ losing++;
else {
- opP->mode=REGLST;
- opP->reg=1<<(opP->reg-DATA);
+ long t;
+
+ t=get_num(opP->con1,80);
+ if(!issbyte(t) || isvar(opP->con1))
+ losing++;
}
- } else if(opP->mode!=REGLST) {
- losing++;
- } else if(s[1]=='8' && opP->reg&0x0FFffFF)
- losing++;
- else if(s[1]=='3' && opP->reg&0x7000000)
- losing++;
- break;
-
- case 'M':
- if(opP->mode!=IMMED)
- losing++;
- else {
- long t;
-
- t=get_num(opP->con1,80);
- if(!issbyte(t) || isvar(opP->con1))
- losing++;
- }
- break;
-
- case 'O':
- if(opP->mode!=DREG && opP->mode!=IMMED)
- losing++;
- break;
-
- case 'Q':
- if(opP->mode!=IMMED)
- losing++;
- else {
- long t;
-
- t=get_num(opP->con1,80);
- if(t<1 || t>8 || isvar(opP->con1))
+ break;
+
+ case 'O':
+ if(opP->mode!=DREG && opP->mode!=IMMED)
+ losing++;
+ break;
+
+ case 'Q':
+ if(opP->mode!=IMMED)
+ losing++;
+ else {
+ long t;
+
+ t=get_num(opP->con1,80);
+ if(t<1 || t>8 || isvar(opP->con1))
+ losing++;
+ }
+ break;
+
+ case 'R':
+ if(opP->mode!=DREG && opP->mode!=AREG)
+ losing++;
+ break;
+
+ case 's':
+ if(opP->mode!=MSCR || !(opP->reg==FPI || opP->reg==FPS || opP->reg==FPC))
+ losing++;
+ break;
+
+ case 'S':
+ if(opP->mode!=MSCR || opP->reg!=SR)
+ losing++;
+ break;
+
+ case 'U':
+ if(opP->mode!=MSCR || opP->reg!=USP)
+ losing++;
+ break;
+
+ /* JF these are out of order. We could put them
+ in order if we were willing to put up with
+ bunches of #ifdef m68851s in the code */
+#ifndef NO_68851
+ /* Memory addressing mode used by pflushr */
+ case '|':
+ if(opP->mode==MSCR || opP->mode==DREG ||
+ opP->mode==AREG || opP->mode==REGLST)
+ losing++;
+ break;
+
+ case 'f':
+ if (opP->mode != MSCR || (opP->reg != SFC && opP->reg != DFC))
+ losing++;
+ break;
+
+ case 'P':
+ if (opP->mode != MSCR || (opP->reg != TC && opP->reg != CAL &&
+ opP->reg != VAL && opP->reg != SCC && opP->reg != AC))
+ losing++;
+ break;
+
+ case 'V':
+ if (opP->reg != VAL)
+ losing++;
+ break;
+
+ case 'W':
+ if (opP->mode != MSCR || (opP->reg != DRP && opP->reg != SRP &&
+ opP->reg != CRP))
+ losing++;
+ break;
+
+ case 'X':
+ if (opP->mode != MSCR ||
+ (!(opP->reg >= BAD && opP->reg <= BAD+7) &&
+ !(opP->reg >= BAC && opP->reg <= BAC+7)))
+ losing++;
+ break;
+
+ case 'Y':
+ if (opP->reg != PSR)
+ losing++;
+ break;
+
+ case 'Z':
+ if (opP->reg != PCSR)
+ losing++;
+ break;
+#endif
+ case 'c':
+ if (opP->reg != NC
+ && opP->reg != IC
+ && opP->reg != DC
+ && opP->reg != BC) {
losing++;
- }
- break;
-
- case 'R':
- if(opP->mode!=DREG && opP->mode!=AREG)
- losing++;
- break;
-
- case 's':
- if(opP->mode!=MSCR || !(opP->reg==FPI || opP->reg==FPS || opP->reg==FPC))
- losing++;
- break;
-
- case 'S':
- if(opP->mode!=MSCR || opP->reg!=SR)
- losing++;
- break;
-
- case 'U':
- if(opP->mode!=MSCR || opP->reg!=USP)
- losing++;
- break;
-
- /* JF these are out of order. We could put them
- in order if we were willing to put up with
- bunches of #ifdef m68851s in the code */
-#ifdef m68851
- /* Memory addressing mode used by pflushr */
- case '|':
- if(opP->mode==MSCR || opP->mode==DREG ||
- opP->mode==AREG || opP->mode==REGLST)
- losing++;
- break;
-
- case 'f':
- if (opP->mode != MSCR || (opP->reg != SFC && opP->reg != DFC))
- losing++;
- break;
-
- case 'P':
- if (opP->mode != MSCR || (opP->reg != TC && opP->reg != CAL &&
- opP->reg != VAL && opP->reg != SCC && opP->reg != AC))
- losing++;
- break;
-
- case 'V':
- if (opP->reg != VAL)
- losing++;
- break;
-
- case 'W':
- if (opP->mode != MSCR || (opP->reg != DRP && opP->reg != SRP &&
- opP->reg != CRP))
- losing++;
- break;
-
- case 'X':
- if (opP->mode != MSCR ||
- (!(opP->reg >= BAD && opP->reg <= BAD+7) &&
- !(opP->reg >= BAC && opP->reg <= BAC+7)))
- losing++;
- break;
+ } /* not a cache specifier. */
+ break;
- case 'Y':
- if (opP->reg != PSR)
- losing++;
- break;
+ case '_':
+ if (opP->mode != ABSL) {
+ ++losing;
+ } /* not absolute */
+ break;
- case 'Z':
- if (opP->reg != PCSR)
- losing++;
- break;
-#endif
- default:
- as_fatal("Internal error: Operand mode %c unknown in line %s of file \"%s\"",
- *s, __LINE__, __FILE__);
- }
- }
- if(!losing)
+ default:
+ as_fatal("Internal error: Operand mode %c unknown in line %s of file \"%s\"",
+ *s, __LINE__, __FILE__);
+ } /* switch on type of operand */
+
+ if (losing) break;
+ } /* for each operand */
+ } /* if immediately wrong */
+
+ if (!losing) {
break;
- opcode=opcode->m_next;
- if(!opcode) { /* Fell off the end */
- the_ins.error="instruction/operands mismatch";
+ } /* got it. */
+
+ opcode = opcode->m_next;
+
+ if (!opcode) {
+ the_ins.error = "instruction/operands mismatch";
return;
- }
- losing=0;
+ } /* Fell off the end */
+
+ losing = 0;
}
+
+
the_ins.args=opcode->m_operands;
the_ins.numargs=opcode->m_opnum;
the_ins.numo=opcode->m_codenum;
the_ins.opcode[0]=getone(opcode);
the_ins.opcode[1]=gettwo(opcode);
-
- for(s=the_ins.args,opP= &the_ins.operands[0];*s;s+=2,opP++) {
- /* This switch is a doozy.
- What the first step; its a big one! */
+
+ for (s = the_ins.args, opP = &the_ins.operands[0]; *s; s += 2, opP++) {
+ /* This switch is a doozy.
+ Watch the first step; its a big one! */
switch(s[0]) {
-
+
case '*':
case '~':
case '%':
@@ -1400,7 +1631,7 @@ char *instring;
case '$':
case '?':
case '/':
-#ifdef m68851
+#ifndef NO_68851
case '|':
#endif
switch(opP->mode) {
@@ -1409,17 +1640,17 @@ char *instring;
if (strchr("bwl",s[1])) nextword=get_num(opP->con1,80);
else nextword=nextword=get_num(opP->con1,0);
if(isvar(opP->con1))
- add_fix(s[1],opP->con1,0);
+ add_fix(s[1],opP->con1,0);
switch(s[1]) {
case 'b':
if(!isbyte(nextword))
- opP->error="operand out of range";
+ opP->error="operand out of range";
addword(nextword);
baseo=0;
break;
case 'w':
if(!isword(nextword))
- opP->error="operand out of range";
+ opP->error="operand out of range";
addword(nextword);
baseo=0;
break;
@@ -1428,7 +1659,7 @@ char *instring;
addword(nextword);
baseo=0;
break;
-
+
case 'f':
baseo=2;
outro=8;
@@ -1450,14 +1681,14 @@ char *instring;
*s, s[1], __LINE__, __FILE__);
}
if(!baseo)
- break;
-
+ break;
+
/* We gotta put out some float */
if(seg(opP->con1)!=SEG_BIG) {
int_to_gen(nextword);
gen_to_words(words,baseo,(long int)outro);
for(wordp=words;baseo--;wordp++)
- addword(*wordp);
+ addword(*wordp);
break;
} /* Its BIG */
if(offs(opP->con1)>0) {
@@ -1468,14 +1699,14 @@ char *instring;
}
baseo-=offs(opP->con1);
for(wordp=generic_bignum+offs(opP->con1)-1;offs(opP->con1)--;--wordp)
- addword(*wordp);
+ addword(*wordp);
while(baseo--)
- addword(0);
+ addword(0);
break;
}
gen_to_words(words,baseo,(long)outro);
for (wordp=words;baseo--;wordp++)
- addword(*wordp);
+ addword(*wordp);
break;
case DREG:
tmpreg=opP->reg-DATA; /* 0.dreg */
@@ -1493,83 +1724,88 @@ char *instring;
tmpreg=0x18+opP->reg-ADDR; /* 3.areg */
break;
case AOFF:
-
+
nextword=get_num(opP->con1,80);
/* Force into index mode. Hope this works */
-
+
/* We do the first bit for 32-bit displacements,
and the second bit for 16 bit ones. It is
possible that we should make the default be
WORD instead of LONG, but I think that'd
break GCC, so we put up with a little
inefficiency for the sake of working output.
- */
-
+ */
+
if( !issword(nextword)
|| ( isvar(opP->con1)
&& ( ( opP->con1->e_siz==0
&& flagseen['l']==0)
|| opP->con1->e_siz==3))) {
-
+
if(opP->reg==PC)
- tmpreg=0x3B; /* 7.3 */
+ tmpreg=0x3B; /* 7.3 */
else
- tmpreg=0x30+opP->reg-ADDR; /* 6.areg */
+ tmpreg=0x30+opP->reg-ADDR; /* 6.areg */
if(isvar(opP->con1)) {
if(opP->reg==PC) {
- add_frag(adds(opP->con1),
- offs(opP->con1),
- TAB(PCLEA,SZ_UNDEF));
+ add_frag(adds(opP->con1),
+ offs(opP->con1),
+ TAB(PCLEA,SZ_UNDEF));
break;
} else {
addword(0x0170);
add_fix('l',opP->con1,1);
}
} else
- addword(0x0170);
+ addword(0x0170);
addword(nextword>>16);
} else {
if(opP->reg==PC)
- tmpreg=0x3A; /* 7.2 */
+ tmpreg=0x3A; /* 7.2 */
else
- tmpreg=0x28+opP->reg-ADDR; /* 5.areg */
-
+ tmpreg=0x28+opP->reg-ADDR; /* 5.areg */
+
if(isvar(opP->con1)) {
if(opP->reg==PC) {
add_fix('w',opP->con1,1);
} else
- add_fix('w',opP->con1,0);
- }
+ add_fix('w',opP->con1,0);
+ }
}
addword(nextword);
break;
- case AINDX:
+
case APODX:
case AMIND:
case APRDX:
+ if (max_arch_this_insn < m68020) {
+ max_arch_this_insn = m68020;
+ } /* bump arch */
+ /* intentional fall-through */
+ case AINDX:
nextword=0;
baseo=get_num(opP->con1,80);
outro=get_num(opP->con2,80);
- /* Figure out the 'addressing mode' */
- /* Also turn on the BASE_DISABLE bit, if needed */
+ /* Figure out the 'addressing mode' */
+ /* Also turn on the BASE_DISABLE bit, if needed */
if(opP->reg==PC || opP->reg==ZPC) {
tmpreg=0x3b; /* 7.3 */
if(opP->reg==ZPC)
- nextword|=0x80;
+ nextword|=0x80;
} else if(opP->reg==FAIL) {
nextword|=0x80;
tmpreg=0x30; /* 6.garbage */
} else tmpreg=0x30+opP->reg-ADDR; /* 6.areg */
-
+
siz1= (opP->con1) ? opP->con1->e_siz : 0;
siz2= (opP->con2) ? opP->con2->e_siz : 0;
-
- /* Index register stuff */
+
+ /* Index register stuff */
if(opP->ireg>=DATA+0 && opP->ireg<=ADDR+7) {
nextword|=(opP->ireg-DATA)<<12;
-
+
if(opP->isiz==0 || opP->isiz==3)
- nextword|=0x800;
+ nextword|=0x800;
switch(opP->imul) {
case 1: break;
case 2: nextword|=0x200; break;
@@ -1577,14 +1813,14 @@ char *instring;
case 8: nextword|=0x600; break;
default: as_fatal("failed sanity check.");
}
- /* IF its simple,
- GET US OUT OF HERE! */
-
- /* Must be INDEX, with an index
- register. Address register
- cannot be ZERO-PC, and either
- :b was forced, or we know
- it will fit */
+ /* IF its simple,
+ GET US OUT OF HERE! */
+
+ /* Must be INDEX, with an index
+ register. Address register
+ cannot be ZERO-PC, and either
+ :b was forced, or we know
+ it will fit */
if( opP->mode==AINDX
&& opP->reg!=FAIL
&& opP->reg!=ZPC
@@ -1594,24 +1830,24 @@ char *instring;
nextword +=baseo&0xff;
addword(nextword);
if(isvar(opP->con1))
- add_fix('B',opP->con1,0);
+ add_fix('B',opP->con1,0);
break;
}
} else
- nextword|=0x40; /* No index reg */
-
- /* It aint simple */
+ nextword|=0x40; /* No index reg */
+
+ /* It aint simple */
nextword|=0x100;
- /* If the guy specified a width, we assume that
- it is wide enough. Maybe it isn't. Ifso, we lose
- */
+ /* If the guy specified a width, we assume that
+ it is wide enough. Maybe it isn't. Ifso, we lose
+ */
switch(siz1) {
case 0:
if(isvar(opP->con1) || !issword(baseo)) {
siz1=3;
nextword|=0x30;
} else if(baseo==0)
- nextword|=0x10;
+ nextword|=0x10;
else {
nextword|=0x20;
siz1=2;
@@ -1626,8 +1862,8 @@ char *instring;
nextword|=0x30;
break;
}
-
- /* Figure out innner displacement stuff */
+
+ /* Figure out innner displacement stuff */
if(opP->mode!=AINDX) {
switch(siz2) {
case 0:
@@ -1635,7 +1871,7 @@ char *instring;
siz2=3;
nextword|=0x3;
} else if(outro==0)
- nextword|=0x1;
+ nextword|=0x1;
else {
nextword|=0x2;
siz2=2;
@@ -1654,33 +1890,33 @@ char *instring;
else if(opP->mode==AMIND) nextword|=0x40;
}
addword(nextword);
-
+
if(isvar(opP->con1)) {
if(opP->reg==PC || opP->reg==ZPC) {
add_fix(siz1==3 ? 'l' : 'w',opP->con1,1);
opP->con1->e_exp.X_add_number+=6;
} else
- add_fix(siz1==3 ? 'l' : 'w',opP->con1,0);
+ add_fix(siz1==3 ? 'l' : 'w',opP->con1,0);
}
if(siz1==3)
- addword(baseo>>16);
+ addword(baseo>>16);
if(siz1)
- addword(baseo);
-
+ addword(baseo);
+
if(isvar(opP->con2)) {
if(opP->reg==PC || opP->reg==ZPC) {
add_fix(siz2==3 ? 'l' : 'w',opP->con2,1);
opP->con1->e_exp.X_add_number+=6;
} else
- add_fix(siz2==3 ? 'l' : 'w',opP->con2,0);
+ add_fix(siz2==3 ? 'l' : 'w',opP->con2,0);
}
if(siz2==3)
- addword(outro>>16);
+ addword(outro>>16);
if(siz2)
- addword(outro);
-
+ addword(outro);
+
break;
-
+
case ABSL:
nextword=get_num(opP->con1,80);
switch(opP->con1->e_siz) {
@@ -1698,7 +1934,7 @@ char *instring;
&& !subs(opP->con1)
&& seg(opP->con1) == SEG_TEXT
&& now_seg == SEG_TEXT
- && flagseen['m'] == 0
+ && (current_architecture & m68000up) <= m68010
&& !flagseen['S']
&& !strchr("~%&$?", s[0])) {
tmpreg=0x3A; /* 7.2 */
@@ -1709,17 +1945,17 @@ char *instring;
}
case 3: /* Fall through into long */
if(isvar(opP->con1))
- add_fix('l',opP->con1,0);
-
+ add_fix('l',opP->con1,0);
+
tmpreg=0x39; /* 7.1 mode */
addword(nextword>>16);
addword(nextword);
break;
-
+
case 2: /* Word */
if(isvar(opP->con1))
- add_fix('w',opP->con1,0);
-
+ add_fix('w',opP->con1,0);
+
tmpreg=0x38; /* 7.0 mode */
addword(nextword);
break;
@@ -1732,7 +1968,7 @@ char *instring;
}
install_gen_operand(s[1],tmpreg);
break;
-
+
case '#':
case '^':
switch(s[1]) { /* JF: I hate floating point! */
@@ -1752,29 +1988,29 @@ char *instring;
}
tmpreg=get_num(opP->con1,tmpreg);
if(isvar(opP->con1))
- add_fix(s[1],opP->con1,0);
+ add_fix(s[1],opP->con1,0);
switch(s[1]) {
case 'b': /* Danger: These do no check for
certain types of overflow.
user beware! */
if(!isbyte(tmpreg))
- opP->error="out of range";
+ opP->error="out of range";
insop(tmpreg);
if(isvar(opP->con1))
- the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2;
+ the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2;
break;
case 'w':
if(!isword(tmpreg))
- opP->error="out of range";
+ opP->error="out of range";
insop(tmpreg);
if(isvar(opP->con1))
- the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2;
+ the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2;
break;
case 'l':
insop(tmpreg); /* Because of the way insop works, we put these two out backwards */
insop(tmpreg>>16);
if(isvar(opP->con1))
- the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2;
+ the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2;
break;
case '3':
tmpreg&=0xFF;
@@ -1786,13 +2022,14 @@ char *instring;
as_fatal("Internal error: Unknown mode #%c in line %s of file \"%s\"", s[1], __LINE__, __FILE__);
}
break;
-
+
case '+':
case '-':
case 'A':
+ case 'a':
install_operand(s[1],opP->reg-ADDR);
break;
-
+
case 'B':
tmpreg=get_num(opP->con1,80);
switch(s[1]) {
@@ -1808,8 +2045,8 @@ char *instring;
break;
case 'L':
long_branch:
- if(flagseen['m']) /* 68000 or 010 */
- as_warn("Can't use long branches on 68000/68010");
+ if(current_architecture <= m68010) /* 68000 or 010 */
+ as_warn("Can't use long branches on 68000/68010");
the_ins.opcode[the_ins.numo-1]|=0xff;
/* Offset the displacement to be relative to byte disp location */
opP->con1->e_exp.X_add_number+=4;
@@ -1819,8 +2056,8 @@ char *instring;
break;
case 'g':
if(subs(opP->con1)) /* We can't relax it */
- goto long_branch;
-
+ goto long_branch;
+
/* This could either be a symbol, or an
absolute address. No matter, the
frag hacking will finger it out.
@@ -1829,7 +2066,7 @@ char *instring;
where opnd is absolute (it needs
to use the 68000 hack since no
conditional abs jumps). */
- if ((flagseen['m'] || (0==adds(opP->con1)))
+ if (((current_architecture <= m68010) || (0==adds(opP->con1)))
&& (the_ins.opcode[0] >= 0x6200)
&& (the_ins.opcode[0] <= 0x6f00)) {
add_frag(adds(opP->con1),offs(opP->con1),TAB(BCC68000,SZ_UNDEF));
@@ -1839,15 +2076,15 @@ char *instring;
break;
case 'w':
if(isvar(opP->con1)) {
- /* check for DBcc instruction */
+ /* check for DBcc instruction */
if ((the_ins.opcode[0] & 0xf0f8) ==0x50c8) {
- /* size varies if patch */
- /* needed for long form */
+ /* size varies if patch */
+ /* needed for long form */
add_frag(adds(opP->con1),offs(opP->con1),TAB(DBCC,SZ_UNDEF));
break;
}
-
- /* Don't ask! */
+
+ /* Don't ask! */
opP->con1->e_exp.X_add_number+=2;
add_fix('w',opP->con1,1);
}
@@ -1882,16 +2119,16 @@ char *instring;
s[1], __LINE__, __FILE__);
}
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 , */
@@ -1909,115 +2146,108 @@ char *instring;
}
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;
+ 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;
+ case SFC: tmpreg=0x000; break;
+ case DFC: tmpreg=0x001; break;
+ case CACR: tmpreg=0x002; break;
+ case TC: tmpreg=0x003; break;
+ case ITT0: tmpreg=0x004; break;
+ case ITT1: tmpreg=0x005; break;
+ case DTT0: tmpreg=0x006; break;
+ case DTT1: tmpreg=0x007; 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;
+ case MMUSR: tmpreg=0x805; break;
+ case URP: tmpreg=0x806; break;
+ case SRP: tmpreg=0x807; break;
default:
as_fatal("failed sanity check.");
}
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");
+ 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");
+ 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");
+ as_bad("Floating point register in register list");
insop(tmpreg);
} else if(s[1]=='8') {
if(tmpreg&0x0FFFFFF)
- as_bad("incorrect register in reglist");
+ as_bad("incorrect register in reglist");
install_operand(s[1],tmpreg>>24);
} else {
if(tmpreg&0x700FFFF)
- as_bad("wrong register in floating-point reglist");
+ as_bad("wrong register in floating-point reglist");
else
- install_operand(s[1],tmpreg>>16);
+ 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
+ ? 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;
+ 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;
@@ -2025,18 +2255,29 @@ char *instring;
else as_fatal("failed sanity check.");
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
+
+ case 'c':
+ switch (opP->reg) {
+ case NC: tmpreg = 0; break;
+ case DC: tmpreg = 1; break;
+ case IC: tmpreg = 2; break;
+ case BC: tmpreg = 3; break;
+ default:
+ as_fatal("failed sanity check");
+ } /* switch on cache token */
+ install_operand(s[1], tmpreg);
+ break;
+#ifndef NO_68851
/* JF: These are out of order, I fear. */
case 'f':
switch (opP->reg) {
@@ -2051,7 +2292,7 @@ char *instring;
}
install_operand(s[1],tmpreg);
break;
-
+
case 'P':
switch(opP->reg) {
case TC:
@@ -2074,15 +2315,15 @@ char *instring;
}
install_operand(s[1],tmpreg);
break;
-
+
case 'V':
if (opP->reg == VAL)
- break;
+ break;
as_fatal("failed sanity check.");
-
+
case 'W':
switch(opP->reg) {
-
+
case DRP:
tmpreg=1;
break;
@@ -2097,41 +2338,58 @@ char *instring;
}
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:
as_fatal("failed sanity check.");
}
install_operand(s[1], tmpreg);
break;
case 'Y':
- if (opP->reg == PSR)
- break;
- as_fatal("failed sanity check.");
-
+ know(opP->reg == PSR);
+ break;
case 'Z':
- if (opP->reg == PCSR)
- break;
- as_fatal("failed sanity check.");
+ know(opP->reg == PCSR);
+ break;
#endif /* m68851 */
+ case '_':
+ tmpreg=get_num(opP->con1,80);
+ install_operand(s[1], tmpreg);
+ break;
default:
as_fatal("Internal error: Operand type %c unknown in line %s of file \"%s\"", s[0], __LINE__, __FILE__);
}
}
/* By the time whe get here (FINALLY) the_ins contains the complete
instruction, ready to be emitted. . . */
-}
+} /* m68k_ip() */
+
+/*
+ * get_regs := '/' + ?
+ * | '-' + <register>
+ * | '-' + <register> + ?
+ * | <empty>
+ * ;
+ *
+
+ * The idea here must be to scan in a set of registers but I don't
+ * understand it. Looks awfully sloppy to me but I don't have any doc on
+ * this format so...
+
+ *
+ *
+ */
static int get_regs(i,str,opP)
int i;
@@ -2259,7 +2517,7 @@ int val;
case '8':
the_ins.opcode[1]|=val<<10;
break;
-#ifdef m68851
+#ifndef NO_68851
case '9':
the_ins.opcode[1]|=val<<5;
break;
@@ -2291,6 +2549,13 @@ int val;
case 'w':
case 'l':
break;
+ case 'e':
+ the_ins.opcode[0] |= (val << 6);
+ break;
+ case 'L':
+ the_ins.opcode[1] = (val >> 16);
+ the_ins.opcode[2] = val & 0xffff;
+ break;
case 'c':
default:
as_fatal("failed sanity check.");
@@ -2324,6 +2589,11 @@ int val;
}
} /* install_gen_operand() */
+/*
+ * verify that we have some number of paren pairs, do m68k_ip_op(), and
+ * then deal with the bitfield hack.
+ */
+
static char *crack_operand(str,opP)
register char *str;
register struct m68k_op *opP;
@@ -2383,7 +2653,7 @@ char *s;
#endif
/* This is the guts of the machine-dependent assembler. STR points to a
- machine dependent instruction. This funciton is supposed to emit
+ machine dependent instruction. This function is supposed to emit
the frags/bytes it assembles to.
*/
void
@@ -2398,7 +2668,7 @@ char *str;
int shorts_this_frag;
bzero((char *)(&the_ins),sizeof(the_ins)); /* JF for paranoia sake */
- m68_ip(str);
+ m68k_ip(str);
er=the_ins.error;
if(!er) {
for(n=the_ins.numargs;n;--n)
@@ -2542,7 +2812,7 @@ md_begin()
names. */
register const struct m68k_opcode *ins;
- register struct m68_incant *hack,
+ register struct m68k_incant *hack,
*slak;
register char *retval = 0; /* empty string, or error msg text */
register unsigned int i;
@@ -2553,16 +2823,19 @@ md_begin()
obstack_begin(&robyn,4000);
for (ins = m68k_opcodes; ins < endop; ins++) {
- hack=slak=(struct m68_incant *)obstack_alloc(&robyn,sizeof(struct m68_incant));
+ hack=slak=(struct m68k_incant *)obstack_alloc(&robyn,sizeof(struct m68k_incant));
do {
+ /* we *could* ignore insns that don't match our
+ arch here but just leaving them out of the
+ hash. */
slak->m_operands=ins->args;
slak->m_opnum=strlen(slak->m_operands)/2;
+ slak->m_arch = ins->arch;
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));
+ slak->m_next=(struct m68k_incant *) obstack_alloc(&robyn,sizeof(struct m68k_incant));
ins++;
} else
slak->m_next=0;
@@ -2781,7 +3054,7 @@ register fragS *fragP;
ext=2;
break;
case TAB(BRANCH,LONG):
- if (flagseen['m']) {
+ if (current_architecture <= m68010) {
if (fragP->fr_opcode[0]==0x61) {
fragP->fr_opcode[0]= 0x4E;
fragP->fr_opcode[1]= 0xB9; /* JBSR with ABSL LONG offset */
@@ -3003,7 +3276,7 @@ segT segment;
&& S_GET_SEGMENT(fragP->fr_symbol) == segment) {
fragP->fr_subtype=TAB(TABTYPE(fragP->fr_subtype),BYTE);
break;
- } else if((fragP->fr_symbol == 0) || flagseen['m']) {
+ } else if((fragP->fr_symbol == 0) || (current_architecture <= m68010)) {
/* On 68000, or for absolute value, switch to abs long */
/* FIXME, we should check abs val, pick short or long */
if(fragP->fr_opcode[0]==0x61) {
@@ -3180,7 +3453,7 @@ symbolS *to_symbol;
{
long offset;
- if (flagseen['m']) {
+ if (current_architecture <= m68010) {
offset=to_addr-S_GET_VALUE(to_symbol);
md_number_to_chars(ptr ,(long)0x4EF9,2);
md_number_to_chars(ptr+2,(long)offset,4);
@@ -3422,8 +3695,22 @@ static void s_proc() {
/* s_space is defined in read.c .skip is simply an alias to it. */
-int
-md_parse_option(argP,cntP,vecP)
+/*
+ * md_parse_option
+ * Invocation line includes a switch not recognized by the base assembler.
+ * See if it's a processor-specific option. These are:
+ *
+ * -[A]m[c]68000, -[A]m[c]68008, -[A]m[c]68010, -[A]m[c]68020, -[A]m[c]68030, -[A]m[c]68040
+ * -[A]m[c]68881, -[A]m[c]68882, -[A]m[c]68851
+ * Select the architecture. Instructions or features not
+ * supported by the selected architecture cause fatal
+ * errors. More than one may be specified. The default is
+ * -m68020 -m68851 -m68881. Note that -m68008 is a synonym
+ * for -m68000, and -m68882 is a synonym for -m68881.
+ *
+ */
+
+int md_parse_option(argP,cntP,vecP)
char **argP;
int *cntP;
char ***vecP;
@@ -3436,33 +3723,61 @@ char ***vecP;
case 'S': /* -S means that jbsr's always turn into jsr's. */
break;
+ case 'A':
+ (*argP)++;
+ /* intentional fall-through */
case 'm':
- /* Gas almost ignores this option! */
(*argP)++;
- if(**argP=='c')
+
+ if (**argP=='c') {
(*argP)++;
- if(!strcmp(*argP,"68000"))
- flagseen['m']=2;
- else if(!strcmp(*argP,"68010")) {
+ } /* allow an optional "c" */
+
+ if (!strcmp(*argP, "68000")
+ || !strcmp(*argP, "68008")) {
+ current_architecture |= m68000;
+ } else if (!strcmp(*argP, "68010")) {
#ifdef TE_SUN
omagic= 1<<16|OMAGIC;
#endif
- flagseen['m']=1;
- } else if(!strcmp(*argP,"68020"))
- flagseen['m']=0;
- else
- as_warn("Unknown -m option ignored");
- while(**argP)
- (*argP)++;
+ current_architecture |= m68010;
+
+ } else if (!strcmp(*argP, "68020")) {
+ current_architecture |= m68020;
+
+ } else if (!strcmp(*argP, "68030")) {
+ current_architecture |= m68030;
+
+ } else if (!strcmp(*argP, "68040")) {
+ current_architecture |= m68040;
+
+#ifndef NO_68881
+ } else if (!strcmp(*argP, "68881")
+ || !strcmp(*argP, "68882")) {
+ current_architecture |= m68040;
+
+#endif /* NO_68881 */
+#ifndef NO_68851
+ } else if (!strcmp(*argP,"68851")) {
+ current_architecture |= m68040;
+
+#endif /* NO_68851 */
+ } else {
+ as_warn("Unknown architecture, \"%s\". option ignored", *argP);
+ } /* switch on architecture */
+
+ while(**argP) (*argP)++;
+
break;
case 'p':
if (!strcmp(*argP,"pic")) {
(*argP) += 3;
break; /* -pic, Position Independent Code */
- }
- else
- return 0;
+ } else {
+ return(0);
+ } /* pic or not */
+
default:
return 0;
}
@@ -3477,12 +3792,12 @@ char ***vecP;
main()
{
- struct m68_it the_ins;
+ struct m68k_it the_ins;
char buf[120];
char *cp;
int n;
- m68_ip_begin();
+ m68k_ip_begin();
for(;;) {
if(!gets(buf) || !*buf)
break;
@@ -3494,7 +3809,7 @@ main()
if(is_label(buf))
continue;
bzero(&the_ins,sizeof(the_ins));
- m68_ip(&the_ins,buf);
+ m68k_ip(&the_ins,buf);
if(the_ins.error) {
printf("Error %s in %s\n",the_ins.error,buf);
} else {
@@ -3519,7 +3834,7 @@ main()
(void)putchar('\n');
}
}
- m68_ip_end();
+ m68k_ip_end();
return 0;
}
@@ -3648,192 +3963,6 @@ md_pcrel_from (fixP)
return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
}
-/* Opcode table for m68000/m68020 and m68881.
- Copyright (C) 1989, Free Software Foundation.
-
-This file is part of GDB, the GNU Debugger and GAS, the GNU Assembler.
-
-Both GDB and GAS are free software; you can redistribute 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.
-
-GDB and GAS are 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 GDB or GAS; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* We store four bytes of opcode for all opcodes because that
- is the most any of them need. The actual length of an instruction
- is always at least 2 bytes, and is as much longer as necessary to
- hold the operands it has.
-
- The match component is a mask saying which bits must match
- particular opcode in order for an instruction to be an instance
- of that opcode.
-
- The args component is a string containing two characters
- for each operand of the instruction. The first specifies
- the kind of operand; the second, the place it is stored. */
-
-/* Kinds of operands:
- D data register only. Stored as 3 bits.
- A address register only. Stored as 3 bits.
- R either kind of register. Stored as 4 bits.
- F floating point coprocessor register only. Stored as 3 bits.
- O an offset (or width): immediate data 0-31 or data register.
- Stored as 6 bits in special format for BF... insns.
- + autoincrement only. Stored as 3 bits (number of the address register).
- - autodecrement only. Stored as 3 bits (number of the address register).
- Q quick immediate data. Stored as 3 bits.
- This matches an immediate operand only when value is in range 1 .. 8.
- M moveq immediate data. Stored as 8 bits.
- This matches an immediate operand only when value is in range -128..127
- T trap vector immediate data. Stored as 4 bits.
-
- k K-factor for fmove.p instruction. Stored as a 7-bit constant or
- a three bit register offset, depending on the field type.
-
- # immediate data. Stored in special places (b, w or l)
- which say how many bits to store.
- ^ immediate data for floating point instructions. Special places
- are offset by 2 bytes from '#'...
- B pc-relative address, converted to an offset
- that is treated as immediate data.
- d displacement and register. Stores the register as 3 bits
- and stores the displacement in the entire second word.
-
- C the CCR. No need to store it; this is just for filtering validity.
- S the SR. No need to store, just as with CCR.
- U the USP. No need to store, just as with CCR.
-
- I Coprocessor ID. Not printed if 1. The Coprocessor ID is always
- extracted from the 'd' field of word one, which means that an extended
- coprocessor opcode can be skipped using the 'i' place, if needed.
-
- s System Control register for the floating point coprocessor.
- S List of system control registers for floating point coprocessor.
-
- J Misc register for movec instruction, stored in 'j' format.
- Possible values:
- 000 SFC Source Function Code reg
- 001 DFC Data Function Code reg
- 002 CACR Cache Control Register
- 800 USP User Stack Pointer
- 801 VBR Vector Base reg
- 802 CAAR Cache Address Register
- 803 MSP Master Stack Pointer
- 804 ISP Interrupt Stack Pointer
-
- L Register list of the type d0-d7/a0-a7 etc.
- (New! Improved! Can also hold fp0-fp7, as well!)
- The assembler tries to see if the registers match the insn by
- looking at where the insn wants them stored.
-
- l Register list like L, but with all the bits reversed.
- Used for going the other way. . .
-
- They are all stored as 6 bits using an address mode and a register number;
- they differ in which addressing modes they match.
-
- * all (modes 0-6,7.*)
- ~ alterable memory (modes 2-6,7.0,7.1)(not 0,1,7.~)
- % alterable (modes 0-6,7.0,7.1)(not 7.~)
- ; data (modes 0,2-6,7.*)(not 1)
- @ data, but not immediate (modes 0,2-6,7.? ? ?)(not 1,7.?) This may really be ;, the 68020 book says it is
- ! control (modes 2,5,6,7.*-)(not 0,1,3,4,7.4)
- & alterable control (modes 2,5,6,7.0,7.1)(not 0,1,7.? ? ?)
- $ alterable data (modes 0,2-6,7.0,7.1)(not 1,7.~)
- ? alterable control, or data register (modes 0,2,5,6,7.0,7.1)(not 1,3,4,7.~)
- / control, or data register (modes 0,2,5,6,7.0,7.1,7.2,7.3)(not 1,3,4,7.4)
-*/
-
-/* JF: for the 68851 */
-/*
- I didn't use much imagination in choosing the
- following codes, so many of them aren't very
- mnemonic. -rab
-
- P pmmu register
- Possible values:
- 000 TC Translation Control reg
- 100 CAL Current Access Level
- 101 VAL Validate Access Level
- 110 SCC Stack Change Control
- 111 AC Access Control
-
- W wide pmmu registers
- Possible values:
- 001 DRP Dma Root Pointer
- 010 SRP Supervisor Root Pointer
- 011 CRP Cpu Root Pointer
-
- f function code register
- 0 SFC
- 1 DFC
-
- V VAL register only
-
- X BADx, BACx
- 100 BAD Breakpoint Acknowledge Data
- 101 BAC Breakpoint Acknowledge Control
-
- Y PSR
- Z PCSR
-
- | memory (modes 2-6, 7.*)
-
-*/
-
-/* Places to put an operand, for non-general operands:
- s source, low bits of first word.
- d dest, shifted 9 in first word
- 1 second word, shifted 12
- 2 second word, shifted 6
- 3 second word, shifted 0
- 4 third word, shifted 12
- 5 third word, shifted 6
- 6 third word, shifted 0
- 7 second word, shifted 7
- 8 second word, shifted 10
- D store in both place 1 and place 3; for divul and divsl.
- b second word, low byte
- w second word (entire)
- l second and third word (entire)
- g branch offset for bra and similar instructions.
- The place to store depends on the magnitude of offset.
- t store in both place 7 and place 8; for floating point operations
- c branch offset for cpBcc operations.
- The place to store is word two if bit six of word one is zero,
- and words two and three if bit six of word one is one.
- i Increment by two, to skip over coprocessor extended operands. Only
- works with the 'I' format.
- k Dynamic K-factor field. Bits 6-4 of word 2, used as a register number.
- Also used for dynamic fmovem instruction.
- C floating point coprocessor constant - 7 bits. Also used for static
- K-factors...
- j Movec register #, stored in 12 low bits of second word.
-
- Places to put operand, for general operands:
- d destination, shifted 6 bits in first word
- b source, at low bit of first word, and immediate uses one byte
- w source, at low bit of first word, and immediate uses two bytes
- l source, at low bit of first word, and immediate uses four bytes
- s source, at low bit of first word.
- Used sometimes in contexts where immediate is not allowed anyway.
- f single precision float, low bit of 1st word, immediate uses 4 bytes
- F double precision float, low bit of 1st word, immediate uses 8 bytes
- x extended precision float, low bit of 1st word, immediate uses 12 bytes
- p packed float, low bit of 1st word, immediate uses 12 bytes
-*/
-
-#define one(x) ((x) << 16)
-#define two(x, y) (((x) << 16) + y)
-
/*
* Local Variables:
* comment-column: 0