📄 tc-m68k.c
字号:
if (opP->reg == PC) tmpreg = 0x3A; /* 7.2 */ else tmpreg = 0x28 + opP->reg - ADDR; /* 5.areg */ if (isvar (&opP->disp)) { if (opP->reg == PC) { add_fix ('w', &opP->disp, 1, 0); } else add_fix ('w', &opP->disp, 0, 0); } } addword (nextword); break; case POST: case PRE: case BASE: nextword = 0; baseo = get_num (&opP->disp, 80); if (opP->mode == POST || opP->mode == PRE) outro = get_num (&opP->odisp, 80); /* 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; } else if (opP->reg == 0) { nextword |= 0x80; tmpreg = 0x30; /* 6.garbage */ } else if (opP->reg >= ZADDR0 && opP->reg <= ZADDR7) { nextword |= 0x80; tmpreg = 0x30 + opP->reg - ZADDR0; } else tmpreg = 0x30 + opP->reg - ADDR; /* 6.areg */ siz1 = opP->disp.size; if (opP->mode == POST || opP->mode == PRE) siz2 = opP->odisp.size; else siz2 = SIZE_UNSPEC; /* Index register stuff */ if (opP->index.reg != 0 && opP->index.reg >= DATA && opP->index.reg <= ADDR7) { nextword |= (opP->index.reg - DATA) << 12; if (opP->index.size == SIZE_LONG || (opP->index.size == SIZE_UNSPEC && m68k_index_width_default == SIZE_LONG)) nextword |= 0x800; if ((opP->index.scale != 1 && cpu_of_arch (current_architecture) < m68020) || (opP->index.scale == 8 && arch_coldfire_p (current_architecture))) { opP->error = _("scale factor invalid on this architecture; needs cpu32 or 68020 or higher"); } if (arch_coldfire_p (current_architecture) && opP->index.size == SIZE_WORD) opP->error = _("invalid index size for coldfire"); switch (opP->index.scale) { case 1: break; case 2: nextword |= 0x200; break; case 4: nextword |= 0x400; break; case 8: nextword |= 0x600; break; default: abort (); } /* 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. For a 68000 or 68010, force this mode anyways, because the larger modes aren't supported. */ if (opP->mode == BASE && ((opP->reg >= ADDR0 && opP->reg <= ADDR7) || opP->reg == PC)) { if (siz1 == SIZE_BYTE || cpu_of_arch (current_architecture) < m68020 || arch_coldfire_p (current_architecture) || (siz1 == SIZE_UNSPEC && ! isvar (&opP->disp) && issbyte (baseo))) { nextword += baseo & 0xff; addword (nextword); if (isvar (&opP->disp)) { /* Do a byte relocation. If it doesn't fit (possible on m68000) let the fixup processing complain later. */ if (opP->reg == PC) add_fix ('B', &opP->disp, 1, 1); else add_fix ('B', &opP->disp, 0, 0); } else if (siz1 != SIZE_BYTE) { if (siz1 != SIZE_UNSPEC) as_warn (_("Forcing byte displacement")); if (! issbyte (baseo)) opP->error = _("byte displacement out of range"); } break; } else if (siz1 == SIZE_UNSPEC && opP->reg == PC && isvar (&opP->disp) && subs (&opP->disp) == NULL#ifdef OBJ_ELF /* If the displacement needs pic relocation it cannot be relaxed. */ && opP->disp.pic_reloc == pic_none#endif ) { /* The code in md_convert_frag_1 needs to be able to adjust nextword. Call frag_grow to ensure that we have enough space in the frag obstack to make all the bytes contiguous. */ frag_grow (14); nextword += baseo & 0xff; addword (nextword); add_frag (adds (&opP->disp), offs (&opP->disp), TAB (PCINDEX, SZ_UNDEF)); break; } } } else { nextword |= 0x40; /* No index reg */ if (opP->index.reg >= ZDATA0 && opP->index.reg <= ZDATA7) nextword |= (opP->index.reg - ZDATA0) << 12; else if (opP->index.reg >= ZADDR0 || opP->index.reg <= ZADDR7) nextword |= (opP->index.reg - ZADDR0 + 8) << 12; } /* It isn't simple. */ if (cpu_of_arch (current_architecture) < m68020 || arch_coldfire_p (current_architecture)) opP->error = _("invalid operand mode for this architecture; needs 68020 or higher"); nextword |= 0x100; /* If the guy specified a width, we assume that it is wide enough. Maybe it isn't. If so, we lose. */ switch (siz1) { case SIZE_UNSPEC: if (isvar (&opP->disp) ? m68k_rel32 : ! issword (baseo)) { siz1 = SIZE_LONG; nextword |= 0x30; } else if (! isvar (&opP->disp) && baseo == 0) nextword |= 0x10; else { nextword |= 0x20; siz1 = SIZE_WORD; } break; case SIZE_BYTE: as_warn (_(":b not permitted; defaulting to :w")); /* Fall through. */ case SIZE_WORD: nextword |= 0x20; break; case SIZE_LONG: nextword |= 0x30; break; } /* Figure out innner displacement stuff */ if (opP->mode == POST || opP->mode == PRE) { if (cpu_of_arch (current_architecture) & cpu32) opP->error = _("invalid operand mode for this architecture; needs 68020 or higher"); switch (siz2) { case SIZE_UNSPEC: if (isvar (&opP->odisp) ? m68k_rel32 : ! issword (outro)) { siz2 = SIZE_LONG; nextword |= 0x3; } else if (! isvar (&opP->odisp) && outro == 0) nextword |= 0x1; else { nextword |= 0x2; siz2 = SIZE_WORD; } break; case 1: as_warn (_(":b not permitted; defaulting to :w")); /* Fall through. */ case 2: nextword |= 0x2; break; case 3: nextword |= 0x3; break; } if (opP->mode == POST && (nextword & 0x40) == 0) nextword |= 0x04; } addword (nextword); if (siz1 != SIZE_UNSPEC && isvar (&opP->disp)) { if (opP->reg == PC || opP->reg == ZPC) add_fix (siz1 == SIZE_LONG ? 'l' : 'w', &opP->disp, 1, 2); else add_fix (siz1 == SIZE_LONG ? 'l' : 'w', &opP->disp, 0, 0); } if (siz1 == SIZE_LONG) addword (baseo >> 16); if (siz1 != SIZE_UNSPEC) addword (baseo); if (siz2 != SIZE_UNSPEC && isvar (&opP->odisp)) add_fix (siz2 == SIZE_LONG ? 'l' : 'w', &opP->odisp, 0, 0); if (siz2 == SIZE_LONG) addword (outro >> 16); if (siz2 != SIZE_UNSPEC) addword (outro); break; case ABSL: nextword = get_num (&opP->disp, 80); switch (opP->disp.size) { default: abort (); case SIZE_UNSPEC: if (!isvar (&opP->disp) && issword (offs (&opP->disp))) { tmpreg = 0x38; /* 7.0 */ addword (nextword); break; } if (isvar (&opP->disp) && !subs (&opP->disp) && adds (&opP->disp)#ifdef OBJ_ELF /* If the displacement needs pic relocation it cannot be relaxed. */ && opP->disp.pic_reloc == pic_none#endif && !flag_long_jumps && !strchr ("~%&$?", s[0])) { tmpreg = 0x3A; /* 7.2 */ add_frag (adds (&opP->disp), offs (&opP->disp), TAB (ABSTOPCREL, SZ_UNDEF)); break; } /* Fall through into long */ case SIZE_LONG: if (isvar (&opP->disp)) add_fix ('l', &opP->disp, 0, 0); tmpreg = 0x39;/* 7.1 mode */ addword (nextword >> 16); addword (nextword); break; case SIZE_BYTE: as_bad (_("unsupported byte value; use a different suffix")); /* Fall through. */ case SIZE_WORD: /* Word */ if (isvar (&opP->disp)) add_fix ('w', &opP->disp, 0, 0); tmpreg = 0x38;/* 7.0 mode */ addword (nextword); break; } break; case CONTROL: case FPREG: default: as_bad (_("unknown/incorrect operand")); /* abort (); */ } install_gen_operand (s[1], tmpreg); break; case '#': case '^': switch (s[1]) { /* JF: I hate floating point! */ case 'j': tmpreg = 70; break; case '8': tmpreg = 20; break; case 'C': tmpreg = 50; break; case '3': default: tmpreg = 80; break; } tmpreg = get_num (&opP->disp, tmpreg); if (isvar (&opP->disp)) add_fix (s[1], &opP->disp, 0, 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"); insop (tmpreg, opcode); if (isvar (&opP->disp)) the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2 + 1; break; case 'B': if (!issbyte (tmpreg)) opP->error = _("out of range"); the_ins.opcode[the_ins.numo - 1] |= tmpreg & 0xff; if (isvar (&opP->disp)) the_ins.reloc[the_ins.nrel - 1].n = opcode->m_codenum * 2 - 1; break; case 'w': if (!isword (tmpreg)) opP->error = _("out of range"); insop (tmpreg, opcode); if (isvar (&opP->disp)) the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2; break; case 'W': if (!issword (tmpreg)) opP->error = _("out of range"); insop (tmpreg, opcode); if (isvar (&opP->disp)) the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2; break; case 'l': /* Because of the way insop works, we put these two out backwards. */ insop (tmpreg, opcode); insop (tmpreg >> 16, opcode); if (isvar (&opP->disp)) the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2; break; case '3': tmpreg &= 0xFF; case '8': case 'C': case 'j': install_operand (s[1], tmpreg); break; default: abort (); } break; case '+': case '-': case 'A': case 'a': install_operand (s[1], opP->reg - ADDR); break; case 'B': tmpreg = get_num (&opP->disp, 80); switch (s[1]) { case 'B': add_fix ('B', &opP->disp, 1, -1); break; case 'W': add_fix ('w', &opP->disp, 1, 0); addword (0); break; case 'L': long_branch: if (! HAVE_LONG_BRANCH (current_architecture)) as_warn (_("Can't use long branches on 68000/68010/5200")); the_ins.opcode[0] |= 0xff; add_fix ('l', &opP->disp, 1, 0); addword (0); addword (0); break; case 'g': if (subs (&opP->disp)) /* We can't relax it */ goto long_branch;#ifdef OBJ_ELF /* If the displacement needs pic relocation it cannot be relaxed. */ if (opP->disp.pic_reloc != pic_none) goto long_branch;#endif /* This could either be a symbol, or an absolute address. If it's an absolute address, turn it into an absolute jump right here and keep it out of the relaxer. */ if (adds (&opP->disp) == 0) { if (the_ins.opcode[0] == 0x6000) /* jbra */ the_ins.opcode[0] = 0x4EF1; else if (the_ins.opcode[0] == 0x6100) /* jbsr */ the_ins.opcode[0] = 0x4EB1; else /* jCC */ { the_ins.opcode[0] ^= 0x0100; the_ins.opcode[0] |= 0x0006; addword (0x4EF1); } add_fix ('l', &opP->disp, 0, 0); addword (0); addword (0); break; } /* Now we know it's going into the relaxer. Now figure out which mode. We try in this order of preference: long branch, absolute jump, byte/word branches only. */ if (HAVE_LONG_BRANCH (current_architecture)) add_frag (adds (&opP->disp), offs (&opP->disp), TAB (BRANCHBWL, SZ_UNDEF)); else if (! flag_keep_pcrel) { if ((the_ins.opcode[0] == 0x6000) || (the_ins.opcode[0] == 0x6100)) add_frag (adds (&opP->disp), offs (&opP->disp), TAB (BRABSJUNC, SZ_UNDEF)); else add_frag (adds (&opP->disp), offs (&opP->disp), TAB (BRABSJCOND, SZ_UNDEF)); } else add_frag (adds (&opP->disp), offs (&opP->disp), TAB (BRANCHBW, SZ_UNDEF)); break; case 'w': if (isvar (&opP->disp)) { /* Check for DBcc instructions. We can relax them, but only if we have long branches and/or absolute jumps. */ if (((the_ins.opcode[0] & 0xf0f8) == 0x50c8) && (HAVE_LONG_BRANCH (current_architecture) || (! flag_keep_pcrel))) { if (HAVE_LONG_BRANCH (current_architecture)) add_frag (adds (&opP->disp), offs (&opP->disp), TAB (DBCCLBR, SZ_UNDEF)); else add_frag (adds (&opP->disp), offs (&opP->disp), TAB (DBCCABSJ, SZ_UNDEF)); break; } add_fix ('w', &opP->disp, 1, 0); } addword (0); break; case 'C': /* Fixed size LONG coproc branches */ add_fix ('l', &opP->disp, 1, 0); addword (0); addword (0); break; case 'c': /* Var size Coprocesssor branches */ if (subs (&opP->disp) || (adds (&opP->disp) == 0)) { the_ins.opcode[the_ins.numo - 1] |= 0x40; add_fix ('l', &opP->disp, 1, 0); addword (0); addword (0); } else add_frag (adds (&opP->disp), offs (&opP->disp), TAB (FBRANCH, SZ_UNDEF)); break; default: abort (); } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -