📄 tc-m68k.c
字号:
opP->mask = 1 << (opP->reg - FP0 + 16); break; default: abort (); } opP->mode = REGLST; } } else if (opP->mode == CONTROL) { if (s[1] != '8') losing++; else { switch (opP->reg) { case FPI: opP->mask = 1 << 24; break; case FPS: opP->mask = 1 << 25; break; case FPC: opP->mask = 1 << 26; break; default: losing++; break; } opP->mode = REGLST; } } else if (opP->mode != REGLST) losing++; else if (s[1] == '8' && (opP->mask & 0x0ffffff) != 0) losing++; else if (s[1] == '3' && (opP->mask & 0x7000000) != 0) losing++; break; case 'M': if (opP->mode != IMMED) losing++; else if (opP->disp.exp.X_op != O_constant || ! issbyte (opP->disp.exp.X_add_number)) losing++; else if (! m68k_quick && instring[3] != 'q' && instring[4] != 'q') losing++; break; case 'O': if (opP->mode != DREG && opP->mode != IMMED && opP->mode != ABSL) losing++; break; case 'Q': if (opP->mode != IMMED) losing++; else if (opP->disp.exp.X_op != O_constant || opP->disp.exp.X_add_number < 1 || opP->disp.exp.X_add_number > 8) losing++; else if (! m68k_quick && (strncmp (instring, "add", 3) == 0 || strncmp (instring, "sub", 3) == 0) && instring[3] != 'q') losing++; break; case 'R': if (opP->mode != DREG && opP->mode != AREG) losing++; break; case 'r': if (opP->mode != AINDR && (opP->mode != BASE || (opP->reg != 0 && opP->reg != ZADDR0) || opP->disp.exp.X_op != O_absent || ((opP->index.reg < DATA0 || opP->index.reg > DATA7) && (opP->index.reg < ADDR0 || opP->index.reg > ADDR7)) || opP->index.size != SIZE_UNSPEC || opP->index.scale != 1)) losing++; break; case 's': if (opP->mode != CONTROL || ! (opP->reg == FPI || opP->reg == FPS || opP->reg == FPC)) losing++; break; case 'S': if (opP->mode != CONTROL || opP->reg != SR) losing++; break; case 't': if (opP->mode != IMMED) losing++; else if (opP->disp.exp.X_op != O_constant || opP->disp.exp.X_add_number < 0 || opP->disp.exp.X_add_number > 7) losing++; break; case 'U': if (opP->mode != CONTROL || 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. Don't forget that you need these operands to use 68030 MMU instructions. */#ifndef NO_68851 /* Memory addressing mode used by pflushr */ case '|': if (opP->mode == CONTROL || opP->mode == FPREG || opP->mode == DREG || opP->mode == AREG || opP->mode == REGLST) losing++; /* We should accept immediate operands, but they supposedly have to be quad word, and we don't handle that. I would like to see what a Motorola assembler does before doing something here. */ if (opP->mode == IMMED) losing++; break; case 'f': if (opP->mode != CONTROL || (opP->reg != SFC && opP->reg != DFC)) losing++; break; case '0': if (opP->mode != CONTROL || opP->reg != TC) losing++; break; case '1': if (opP->mode != CONTROL || opP->reg != AC) losing++; break; case '2': if (opP->mode != CONTROL || (opP->reg != CAL && opP->reg != VAL && opP->reg != SCC)) losing++; break; case 'V': if (opP->mode != CONTROL || opP->reg != VAL) losing++; break; case 'W': if (opP->mode != CONTROL || (opP->reg != DRP && opP->reg != SRP && opP->reg != CRP)) losing++; break; case 'X': if (opP->mode != CONTROL || (!(opP->reg >= BAD && opP->reg <= BAD + 7) && !(opP->reg >= BAC && opP->reg <= BAC + 7))) losing++; break; case 'Y': if (opP->mode != CONTROL || opP->reg != PSR) losing++; break; case 'Z': if (opP->mode != CONTROL || opP->reg != PCSR) losing++; break;#endif case 'c': if (opP->mode != CONTROL || (opP->reg != NC && opP->reg != IC && opP->reg != DC && opP->reg != BC)) { losing++; } /* not a cache specifier. */ break; case '_': if (opP->mode != ABSL) ++losing; break; case 'u': if (opP->reg < DATA0L || opP->reg > ADDR7U) losing++; /* FIXME: kludge instead of fixing parser: upper/lower registers are *not* CONTROL registers, but ordinary ones. */ if ((opP->reg >= DATA0L && opP->reg <= DATA7L) || (opP->reg >= DATA0U && opP->reg <= DATA7U)) opP->mode = DREG; else opP->mode = AREG; break; default: abort (); } /* switch on type of operand */ if (losing) break; } /* for each operand */ } /* if immediately wrong */ if (!losing) { break; } /* got it. */ opcode = opcode->m_next; if (!opcode) { if (ok_arch && !(ok_arch & current_architecture)) { char buf[200], *cp; strcpy (buf, _("invalid instruction for this architecture; needs ")); cp = buf + strlen (buf); switch (ok_arch) { case mfloat: strcpy (cp, _("fpu (68040, 68060 or 68881/68882)")); break; case mmmu: strcpy (cp, _("mmu (68030 or 68851)")); 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; for (idx = 0; idx < (int) (sizeof (archs) / sizeof (archs[0])); idx++) { if ((archs[idx].arch & ok_arch) && ! archs[idx].alias) { if (got_one) { strcpy (cp, " or "); cp += strlen (cp); } got_one = 1; strcpy (cp, archs[idx].name); cp += strlen (cp); } } } } cp = xmalloc (strlen (buf) + 1); strcpy (cp, buf); the_ins.error = cp; } else the_ins.error = _("operands mismatch"); return; } /* Fell off the end */ losing = 0; } /* now assemble it */ 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. Watch the first step; its a big one! */ switch (s[0]) { case '*': case '~': case '%': case ';': case '@': case '!': case '&': case '$': case '?': case '/': case '<': case '>': case 'm': case 'n': case 'o': case 'p': case 'q': case 'v':#ifndef NO_68851 case '|':#endif switch (opP->mode) { case IMMED: tmpreg = 0x3c; /* 7.4 */ if (strchr ("bwl", s[1])) nextword = get_num (&opP->disp, 80); else nextword = get_num (&opP->disp, 0); if (isvar (&opP->disp)) add_fix (s[1], &opP->disp, 0, 0); switch (s[1]) { case 'b': if (!isbyte (nextword)) opP->error = _("operand out of range"); addword (nextword); baseo = 0; break; case 'w': if (!isword (nextword)) opP->error = _("operand out of range"); addword (nextword); baseo = 0; break; case 'W': if (!issword (nextword)) opP->error = _("operand out of range"); addword (nextword); baseo = 0; break; case 'l': addword (nextword >> 16); addword (nextword); baseo = 0; break; case 'f': baseo = 2; outro = 8; break; case 'F': baseo = 4; outro = 11; break; case 'x': baseo = 6; outro = 15; break; case 'p': baseo = 6; outro = -1; break; default: abort (); } if (!baseo) break; /* We gotta put out some float */ if (op (&opP->disp) != O_big) { valueT val; int gencnt; /* Can other cases happen here? */ if (op (&opP->disp) != O_constant) abort (); val = (valueT) offs (&opP->disp); gencnt = 0; do { generic_bignum[gencnt] = (LITTLENUM_TYPE) val; val >>= LITTLENUM_NUMBER_OF_BITS; ++gencnt; } while (val != 0); offs (&opP->disp) = gencnt; } if (offs (&opP->disp) > 0) { if (offs (&opP->disp) > baseo) { as_warn (_("Bignum too big for %c format; truncated"), s[1]); offs (&opP->disp) = baseo; } baseo -= offs (&opP->disp); while (baseo--) addword (0); for (wordp = generic_bignum + offs (&opP->disp) - 1; offs (&opP->disp)--; --wordp) addword (*wordp); break; } gen_to_words (words, baseo, (long) outro); for (wordp = words; baseo--; wordp++) addword (*wordp); break; case DREG: tmpreg = opP->reg - DATA; /* 0.dreg */ break; case AREG: tmpreg = 0x08 + opP->reg - ADDR; /* 1.areg */ break; case AINDR: tmpreg = 0x10 + opP->reg - ADDR; /* 2.areg */ break; case ADEC: tmpreg = 0x20 + opP->reg - ADDR; /* 4.areg */ break; case AINC: tmpreg = 0x18 + opP->reg - ADDR; /* 3.areg */ break; case DISP: nextword = get_num (&opP->disp, 80); if (opP->reg == PC && ! isvar (&opP->disp) && m68k_abspcadd) { opP->disp.exp.X_op = O_symbol;#ifndef BFD_ASSEMBLER opP->disp.exp.X_add_symbol = &abs_symbol;#else opP->disp.exp.X_add_symbol = section_symbol (absolute_section);#endif } /* 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->disp) && ((opP->disp.size == SIZE_UNSPEC && flag_short_refs == 0 && cpu_of_arch (current_architecture) >= m68020 && ! arch_coldfire_p (current_architecture)) || opP->disp.size == SIZE_LONG))) { if (cpu_of_arch (current_architecture) < m68020 || arch_coldfire_p (current_architecture)) opP->error = _("displacement too large for this architecture; needs 68020 or higher"); if (opP->reg == PC) tmpreg = 0x3B; /* 7.3 */ else tmpreg = 0x30 + opP->reg - ADDR; /* 6.areg */ if (isvar (&opP->disp)) { if (opP->reg == PC) { if (opP->disp.size == SIZE_LONG#ifdef OBJ_ELF /* If the displacement needs pic relocation it cannot be relaxed. */ || opP->disp.pic_reloc != pic_none#endif ) { addword (0x0170); add_fix ('l', &opP->disp, 1, 2); } else { add_frag (adds (&opP->disp), offs (&opP->disp), TAB (PCREL1632, SZ_UNDEF)); break; } } else { addword (0x0170); add_fix ('l', &opP->disp, 0, 0); } } else addword (0x0170); addword (nextword >> 16); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -