* config/tc-m68k.c (m68k_ip): If instruction is invalid for the

selected architecture, print a message saying so and listing what
processors support it, rather than saying "operands mismatch".
This commit is contained in:
Ken Raeburn
1992-08-15 02:57:12 +00:00
parent 2e20e59abc
commit 8be74775cd

View File

@ -992,6 +992,7 @@ void m68k_ip (instring)
char *crack_operand(); char *crack_operand();
LITTLENUM_TYPE words[6]; LITTLENUM_TYPE words[6];
LITTLENUM_TYPE *wordp; LITTLENUM_TYPE *wordp;
unsigned long ok_arch = 0;
if (*instring == ' ') if (*instring == ' ')
instring++; /* skip leading whitespace */ instring++; /* skip leading whitespace */
@ -1048,7 +1049,6 @@ void m68k_ip (instring)
for(n=opsfound;n>0;--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];
/* memcpy((char *)(&the_ins.operands[1]), (char *)(&the_ins.operands[0]), opsfound*sizeof(the_ins.operands[0])); */
memset((char *)(&the_ins.operands[0]), '\0', sizeof(the_ins.operands[0])); memset((char *)(&the_ins.operands[0]), '\0', sizeof(the_ins.operands[0]));
the_ins.operands[0].mode=MSCR; the_ins.operands[0].mode=MSCR;
the_ins.operands[0].reg=COPNUM; /* COP #1 */ the_ins.operands[0].reg=COPNUM; /* COP #1 */
@ -1062,325 +1062,327 @@ void m68k_ip (instring)
then reject this pattern. */ then reject this pattern. */
if (opsfound != opcode->m_opnum if (opsfound != opcode->m_opnum
|| ((opcode->m_arch & current_architecture) == 0)) { || ((opcode->m_arch & current_architecture) == 0))
{
++losing;
ok_arch |= opcode->m_arch;
}
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;
++losing; case '#':
if(opP->mode!=IMMED)
losing++;
else {
long t;
} else { t=get_num(opP->con1,80);
for (s=opcode->m_operands, opP = &the_ins.operands[0]; *s && !losing; s += 2, opP++) { if(s[1]=='b' && !isbyte(t))
/* Warning: this switch is huge! */ losing++;
/* I've tried to organize the cases into this order: else if(s[1]=='w' && !isword(t))
non-alpha first, then alpha by letter. lower-case goes directly losing++;
before uppercase counterpart. */ }
/* Code with multiple case ...: gets sorted by the lowest case ... break;
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 '#': case '^':
if(opP->mode!=IMMED) case 'T':
losing++; if(opP->mode!=IMMED)
else { losing++;
long t; break;
t=get_num(opP->con1,80); case '$':
if(s[1]=='b' && !isbyte(t)) if(opP->mode==MSCR || opP->mode==AREG ||
losing++; opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || opP->mode==REGLST)
else if(s[1]=='w' && !isword(t)) losing++;
losing++; break;
}
break;
case '^': case '%':
case 'T': if(opP->mode==MSCR || opP->reg==PC ||
if(opP->mode!=IMMED) opP->reg==ZPC || opP->mode==REGLST)
losing++; losing++;
break; 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 '&': case '&':
if(opP->mode==MSCR || opP->mode==DREG || if(opP->mode==MSCR || opP->mode==DREG ||
opP->mode==AREG || opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || opP->mode==AREG || opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC ||
opP->mode==AINC || opP->mode==ADEC || opP->mode==REGLST) opP->mode==AINC || opP->mode==ADEC || opP->mode==REGLST)
losing++; losing++;
break; break;
case '*': case '*':
if(opP->mode==MSCR || opP->mode==REGLST) if(opP->mode==MSCR || opP->mode==REGLST)
losing++; losing++;
break; break;
case '+': case '+':
if(opP->mode!=AINC) if(opP->mode!=AINC)
losing++; losing++;
break; break;
case '-': case '-':
if(opP->mode!=ADEC) if(opP->mode!=ADEC)
losing++; losing++;
break; break;
case '/': case '/':
if(opP->mode==MSCR || opP->mode==AREG || if(opP->mode==MSCR || opP->mode==AREG ||
opP->mode==AINC || opP->mode==ADEC || opP->mode==IMMED || opP->mode==REGLST) opP->mode==AINC || opP->mode==ADEC || opP->mode==IMMED || opP->mode==REGLST)
losing++; losing++;
break; break;
case ';': case ';':
if(opP->mode==MSCR || opP->mode==AREG || opP->mode==REGLST) if(opP->mode==MSCR || opP->mode==AREG || opP->mode==REGLST)
losing++; losing++;
break; break;
case '?': case '?':
if(opP->mode==MSCR || opP->mode==AREG || if(opP->mode==MSCR || opP->mode==AREG ||
opP->mode==AINC || opP->mode==ADEC || opP->mode==IMMED || opP->reg==PC || opP->mode==AINC || opP->mode==ADEC || opP->mode==IMMED || opP->reg==PC ||
opP->reg==ZPC || opP->mode==REGLST) opP->reg==ZPC || opP->mode==REGLST)
losing++; losing++;
break; break;
case '@': case '@':
if(opP->mode==MSCR || opP->mode==AREG || if(opP->mode==MSCR || opP->mode==AREG ||
opP->mode==IMMED || opP->mode==REGLST) opP->mode==IMMED || opP->mode==REGLST)
losing++; losing++;
break; break;
case '~': /* For now! (JF FOO is this right?) */ case '~': /* For now! (JF FOO is this right?) */
if(opP->mode==MSCR || opP->mode==DREG || if(opP->mode==MSCR || opP->mode==DREG ||
opP->mode==AREG || opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || opP->mode==REGLST) opP->mode==AREG || opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || opP->mode==REGLST)
losing++; losing++;
break; break;
case 'A': case 'A':
if(opP->mode!=AREG) if(opP->mode!=AREG)
losing++; losing++;
break; break;
case 'a': case 'a':
if (opP->mode != AINDR) { if (opP->mode != AINDR) {
++losing; ++losing;
} /* if not address register indirect */ } /* if not address register indirect */
break; break;
case 'B': /* FOO */ case 'B': /* FOO */
if(opP->mode!=ABSL || (flagseen['S'] && instring[0] == 'j' if(opP->mode!=ABSL || (flagseen['S'] && instring[0] == 'j'
&& instring[1] == 'b' && instring[1] == 'b'
&& instring[2] == 's' && instring[2] == 's'
&& instring[3] == 'r')) && instring[3] == 'r'))
losing++; losing++;
break; break;
case 'C': case 'C':
if(opP->mode!=MSCR || opP->reg!=CCR) if(opP->mode!=MSCR || opP->reg!=CCR)
losing++; losing++;
break; break;
case 'd': /* FOO This mode is a KLUDGE!! */ case 'd': /* FOO This mode is a KLUDGE!! */
if(opP->mode!=AOFF && (opP->mode!=ABSL || if(opP->mode!=AOFF && (opP->mode!=ABSL ||
opP->con1->e_beg[0]!='(' || opP->con1->e_end[0]!=')')) opP->con1->e_beg[0]!='(' || opP->con1->e_end[0]!=')'))
losing++; losing++;
break; break;
case 'D': case 'D':
if(opP->mode!=DREG) if(opP->mode!=DREG)
losing++; losing++;
break; break;
case 'F': case 'F':
if(opP->mode!=MSCR || opP->reg<(FPREG+0) || opP->reg>(FPREG+7)) if(opP->mode!=MSCR || opP->reg<(FPREG+0) || opP->reg>(FPREG+7))
losing++; losing++;
break; break;
case 'I': case 'I':
if(opP->mode!=MSCR || opP->reg<COPNUM || if(opP->mode!=MSCR || opP->reg<COPNUM ||
opP->reg>=COPNUM+7) opP->reg>=COPNUM+7)
losing++; losing++;
break; break;
case 'J': case 'J':
if (opP->mode != MSCR if (opP->mode != MSCR
|| opP->reg < USP || opP->reg < USP
|| opP->reg > URP || opP->reg > URP
|| cpu_of_arch(current_architecture) < m68010 /* before 68010 had none */ || cpu_of_arch(current_architecture) < m68010 /* before 68010 had none */
|| (cpu_of_arch(current_architecture) < m68020 || (cpu_of_arch(current_architecture) < m68020
&& opP->reg != SFC && opP->reg != SFC
&& opP->reg != DFC && opP->reg != DFC
&& opP->reg != USP && opP->reg != USP
&& opP->reg != VBR) /* 68010's had only these */ && opP->reg != VBR) /* 68010's had only these */
|| (cpu_of_arch(current_architecture) < m68040 || (cpu_of_arch(current_architecture) < m68040
&& opP->reg != SFC && opP->reg != SFC
&& opP->reg != DFC && opP->reg != DFC
&& opP->reg != USP && opP->reg != USP
&& opP->reg != VBR && opP->reg != VBR
&& opP->reg != CACR && opP->reg != CACR
&& opP->reg != CAAR && opP->reg != CAAR
&& opP->reg != MSP && opP->reg != MSP
&& opP->reg != ISP) /* 680[23]0's have only these */ && opP->reg != ISP) /* 680[23]0's have only these */
|| (cpu_of_arch(current_architecture) == m68040 /* 68040 has all but this */ || (cpu_of_arch(current_architecture) == m68040 /* 68040 has all but this */
&& opP->reg == CAAR)) { && opP->reg == CAAR)) {
losing++; losing++;
} /* doesn't cut it */ } /* doesn't cut it */
break; break;
case 'k': case 'k':
if(opP->mode!=IMMED) if(opP->mode!=IMMED)
losing++; losing++;
break; break;
case 'l': case 'l':
case 'L': case 'L':
if(opP->mode==DREG || opP->mode==AREG || opP->mode==FPREG) { if(opP->mode==DREG || opP->mode==AREG || opP->mode==FPREG) {
if(s[1]=='8') if(s[1]=='8')
losing++; losing++;
else { else {
opP->mode=REGLST; opP->mode=REGLST;
opP->reg=1<<(opP->reg-DATA); opP->reg=1<<(opP->reg-DATA);
} }
} else if(opP->mode!=REGLST) { } else if(opP->mode!=REGLST) {
losing++; losing++;
} else if(s[1]=='8' && opP->reg&0x0FFffFF) } else if(s[1]=='8' && opP->reg&0x0FFffFF)
losing++; losing++;
else if(s[1]=='3' && opP->reg&0x7000000) else if(s[1]=='3' && opP->reg&0x7000000)
losing++; losing++;
break; break;
case 'M': case 'M':
if(opP->mode!=IMMED) if(opP->mode!=IMMED)
losing++; losing++;
else { else {
long t; long t;
t=get_num(opP->con1,80); t=get_num(opP->con1,80);
if(!issbyte(t) || isvar(opP->con1)) if(!issbyte(t) || isvar(opP->con1))
losing++; losing++;
} }
break; break;
case 'O': case 'O':
if(opP->mode!=DREG && opP->mode!=IMMED) if(opP->mode!=DREG && opP->mode!=IMMED)
losing++; losing++;
break; break;
case 'Q': case 'Q':
if(opP->mode!=IMMED) if(opP->mode!=IMMED)
losing++; losing++;
else { else {
long t; long t;
t=get_num(opP->con1,80); t=get_num(opP->con1,80);
if(t<1 || t>8 || isvar(opP->con1)) if(t<1 || t>8 || isvar(opP->con1))
losing++; losing++;
} }
break; break;
case 'R': case 'R':
if(opP->mode!=DREG && opP->mode!=AREG) if(opP->mode!=DREG && opP->mode!=AREG)
losing++; losing++;
break; break;
case 's': case 's':
if(opP->mode!=MSCR || !(opP->reg==FPI || opP->reg==FPS || opP->reg==FPC)) if(opP->mode!=MSCR || !(opP->reg==FPI || opP->reg==FPS || opP->reg==FPC))
losing++; losing++;
break; break;
case 'S': case 'S':
if(opP->mode!=MSCR || opP->reg!=SR) if(opP->mode!=MSCR || opP->reg!=SR)
losing++; losing++;
break; break;
case 'U': case 'U':
if(opP->mode!=MSCR || opP->reg!=USP) if(opP->mode!=MSCR || opP->reg!=USP)
losing++; losing++;
break; break;
/* JF these are out of order. We could put them /* JF these are out of order. We could put them
in order if we were willing to put up with in order if we were willing to put up with
bunches of #ifdef m68851s in the code */ bunches of #ifdef m68851s in the code */
#ifndef NO_68851 #ifndef NO_68851
/* Memory addressing mode used by pflushr */ /* Memory addressing mode used by pflushr */
case '|': case '|':
if(opP->mode==MSCR || opP->mode==DREG || if(opP->mode==MSCR || opP->mode==DREG ||
opP->mode==AREG || opP->mode==REGLST) opP->mode==AREG || opP->mode==REGLST)
losing++; losing++;
break; break;
case 'f': case 'f':
if (opP->mode != MSCR || (opP->reg != SFC && opP->reg != DFC)) if (opP->mode != MSCR || (opP->reg != SFC && opP->reg != DFC))
losing++; losing++;
break; break;
case 'P': case 'P':
if (opP->mode != MSCR || (opP->reg != TC && opP->reg != CAL && if (opP->mode != MSCR || (opP->reg != TC && opP->reg != CAL &&
opP->reg != VAL && opP->reg != SCC && opP->reg != AC)) opP->reg != VAL && opP->reg != SCC && opP->reg != AC))
losing++; losing++;
break; break;
case 'V': case 'V':
if (opP->reg != VAL) if (opP->reg != VAL)
losing++; losing++;
break; break;
case 'W': case 'W':
if (opP->mode != MSCR || (opP->reg != DRP && opP->reg != SRP && if (opP->mode != MSCR || (opP->reg != DRP && opP->reg != SRP &&
opP->reg != CRP)) opP->reg != CRP))
losing++; losing++;
break; break;
case 'X': case 'X':
if (opP->mode != MSCR || if (opP->mode != MSCR ||
(!(opP->reg >= BAD && opP->reg <= BAD+7) && (!(opP->reg >= BAD && opP->reg <= BAD+7) &&
!(opP->reg >= BAC && opP->reg <= BAC+7))) !(opP->reg >= BAC && opP->reg <= BAC+7)))
losing++; losing++;
break; break;
case 'Y': case 'Y':
if (opP->reg != PSR) if (opP->reg != PSR)
losing++; losing++;
break; break;
case 'Z': case 'Z':
if (opP->reg != PCSR) if (opP->reg != PCSR)
losing++; losing++;
break; break;
#endif #endif
case 'c': case 'c':
if (opP->reg != NC if (opP->reg != NC
&& opP->reg != IC && opP->reg != IC
&& opP->reg != DC && opP->reg != DC
&& opP->reg != BC) { && opP->reg != BC) {
losing++; losing++;
} /* not a cache specifier. */ } /* not a cache specifier. */
break; break;
case '_': case '_':
if (opP->mode != ABSL) { if (opP->mode != ABSL) {
++losing; ++losing;
} /* not absolute */ } /* not absolute */
break; break;
default: default:
as_fatal("Internal error: Operand mode %c unknown in line %s of file \"%s\"", as_fatal("Internal error: Operand mode %c unknown in line %s of file \"%s\"",
*s, __LINE__, __FILE__); *s, __LINE__, __FILE__);
} /* switch on type of operand */ } /* switch on type of operand */
if (losing) break; if (losing)
} /* for each operand */ break;
} /* if immediately wrong */ } /* for each operand */
} /* if immediately wrong */
if (!losing) { if (!losing) {
break; break;
@ -1389,7 +1391,67 @@ void m68k_ip (instring)
opcode = opcode->m_next; opcode = opcode->m_next;
if (!opcode) { if (!opcode) {
the_ins.error = "instruction/operands mismatch or invalid\n instruction for this architecture"; if (ok_arch)
{
char buf[200], *cp;
int len;
strcpy (buf, "invalid instruction for this architecture; needs ");
cp = buf + strlen (buf);
switch (ok_arch)
{
case mfloat:
strcpy (cp, "fpu");
break;
case mmmu:
strcpy (cp, "mmu");
break;
case m68020up:
strcpy (cp, "68020 or higher");
break;
case m68000up:
strcpy (cp, "68000 or higher");
break;
case m68010up:
strcpy (cp, "68010 or higher");
break;
default:
{
int got_one = 0, idx;
const static struct {
enum m68k_architecture arch;
const char *name;
} archs[] = {
m68000, "68000",
m68010, "68010",
m68020, "68020",
m68030, "68030",
m68040, "68040",
m68881, "68881",
m68851, "68851",
};
for (idx = 0; idx < sizeof (archs)/sizeof (archs[0]); idx++)
{
if (archs[idx].arch & ok_arch)
{
if (got_one)
{
strcpy (cp, " or ");
cp += strlen (cp);
}
got_one = 1;
strcpy (cp, archs[idx].name);
cp += strlen (cp);
}
}
}
}
len = cp - buf + 1;
cp = malloc (len);
strcpy (cp, buf);
the_ins.error = cp;
}
else
the_ins.error = "operands mismatch";
return; return;
} /* Fell off the end */ } /* Fell off the end */